From b4eba3fadc88d8bbc128f05b82eddc37126979b0 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 13:07:48 +0900 Subject: [PATCH 01/38] =?UTF-8?q?[PC-380]=20fix:=20Profile=20Base=20Entity?= =?UTF-8?q?=20=EC=83=81=EC=86=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/src/main/java/org/yapp/domain/profile/Profile.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/src/main/java/org/yapp/domain/profile/Profile.java b/common/src/main/java/org/yapp/domain/profile/Profile.java index 4584f45..c333fdc 100644 --- a/common/src/main/java/org/yapp/domain/profile/Profile.java +++ b/common/src/main/java/org/yapp/domain/profile/Profile.java @@ -15,6 +15,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; import org.yapp.domain.user.User; @Table(name = "profile") @@ -23,7 +24,7 @@ @NoArgsConstructor @AllArgsConstructor @Builder -public class Profile { +public class Profile extends BaseEntity { @Id @Column(name = "profile_id") From 9c2b43b4e9ffe7ba1009949bf87ebdf965dfb85e Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 13:22:54 +0900 Subject: [PATCH 02/38] =?UTF-8?q?[PC-380]=20feat:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20status=20=EC=BB=AC=EB=9F=BC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/yapp/domain/profile/Profile.java | 6 ++++ .../yapp/domain/profile/ProfileStatus.java | 29 +++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileStatus.java diff --git a/common/src/main/java/org/yapp/domain/profile/Profile.java b/common/src/main/java/org/yapp/domain/profile/Profile.java index c333fdc..87eda30 100644 --- a/common/src/main/java/org/yapp/domain/profile/Profile.java +++ b/common/src/main/java/org/yapp/domain/profile/Profile.java @@ -4,6 +4,8 @@ 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; @@ -34,6 +36,10 @@ public class Profile extends BaseEntity { @OneToOne(mappedBy = "profile") private User user; + @Enumerated(EnumType.STRING) + @Builder.Default + private ProfileStatus status = ProfileStatus.INCOMPLETE; + @Embedded private ProfileBasic profileBasic; diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileStatus.java b/common/src/main/java/org/yapp/domain/profile/ProfileStatus.java new file mode 100644 index 0000000..1cfe51f --- /dev/null +++ b/common/src/main/java/org/yapp/domain/profile/ProfileStatus.java @@ -0,0 +1,29 @@ +package org.yapp.domain.profile; + +public enum ProfileStatus { + + INCOMPLETE("미완료"), + REJECTED("보류"), + REVISED("수정 제출"), + APPROVED("통과"); + + private final String displayName; + + + ProfileStatus(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + + public static ProfileStatus fromDisplayName(String displayName) { + for (ProfileStatus status : ProfileStatus.values()) { + if (status.displayName.equals(displayName)) { + return status; + } + } + throw new IllegalArgumentException("Invalid display name: " + displayName); + } +} From 58cf4c6cd76006d5f8c787e23c382be13eb70ce9 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 13:29:42 +0900 Subject: [PATCH 03/38] =?UTF-8?q?[PC-380]=20feat:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EB=A6=AC=EC=A0=9D=20=EB=A1=9C=EA=B7=B8=20=ED=85=8C?= =?UTF-8?q?=EC=9D=B4=EB=B8=94=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/profile/ProfileRejectHistory.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java b/common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java new file mode 100644 index 0000000..727d692 --- /dev/null +++ b/common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java @@ -0,0 +1,34 @@ +package org.yapp.domain.profile; + +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.OneToOne; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.user.User; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ProfileRejectHistory extends BaseEntity { + + @Id + @Column(name = "profile_reject_history_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne() + @JoinColumn(name = "user_id") + private User user; + + boolean reasonImage; + + boolean reasonDescription; +} From 35985f5b7710ca66cdd653593ceef41e12e5c4fc Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 13:40:41 +0900 Subject: [PATCH 04/38] =?UTF-8?q?[PC-380]=20refactor:=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8A=94=20=ED=81=B4=EB=9E=98?= =?UTF-8?q?=EC=8A=A4=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/main/java/org/yapp/Main.java | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 admin/src/main/java/org/yapp/Main.java diff --git a/admin/src/main/java/org/yapp/Main.java b/admin/src/main/java/org/yapp/Main.java deleted file mode 100644 index dce3f50..0000000 --- a/admin/src/main/java/org/yapp/Main.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.yapp; - -public class Main { - public static void main(String[] args) { - System.out.println("Hello world!"); - } -} \ No newline at end of file From 2a3f4ac224f7f52aa7d37709eb8bc7f4a5d58a24 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 14:56:14 +0900 Subject: [PATCH 05/38] =?UTF-8?q?[PC-380]=20refactor:=20common:domain=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/yapp/domain/BaseEntity.java | 24 +++++++ .../java/org/yapp/domain/block/Block.java | 46 ++++++++++++ .../java/org/yapp/domain/match/MatchInfo.java | 44 ++++++++++++ .../java/org/yapp/domain/profile/Profile.java | 71 +++++++++++++++++++ .../org/yapp/domain/profile/ProfileBasic.java | 55 ++++++++++++++ .../org/yapp/domain/profile/ProfileBio.java | 26 +++++++ .../domain/profile/ProfileRejectHistory.java | 36 ++++++++++ .../yapp/domain/profile/ProfileStatus.java | 29 ++++++++ .../yapp/domain/profile/ProfileValuePick.java | 53 ++++++++++++++ .../yapp/domain/profile/ProfileValueTalk.java | 52 ++++++++++++++ .../main/java/org/yapp/domain/term/Term.java | 41 +++++++++++ .../org/yapp/domain/term/TermAgreement.java | 40 +++++++++++ .../main/java/org/yapp/domain/user/User.java | 59 +++++++++++++++ .../java/org/yapp/domain/value/ValuePick.java | 42 +++++++++++ .../java/org/yapp/domain/value/ValueTalk.java | 40 +++++++++++ 15 files changed, 658 insertions(+) create mode 100644 common/domain/src/main/java/org/yapp/domain/BaseEntity.java create mode 100644 common/domain/src/main/java/org/yapp/domain/block/Block.java create mode 100644 common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/Profile.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/ProfileBasic.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/ProfileBio.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/ProfileStatus.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/ProfileValuePick.java create mode 100644 common/domain/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java create mode 100644 common/domain/src/main/java/org/yapp/domain/term/Term.java create mode 100644 common/domain/src/main/java/org/yapp/domain/term/TermAgreement.java create mode 100644 common/domain/src/main/java/org/yapp/domain/user/User.java create mode 100644 common/domain/src/main/java/org/yapp/domain/value/ValuePick.java create mode 100644 common/domain/src/main/java/org/yapp/domain/value/ValueTalk.java diff --git a/common/domain/src/main/java/org/yapp/domain/BaseEntity.java b/common/domain/src/main/java/org/yapp/domain/BaseEntity.java new file mode 100644 index 0000000..1bf7cfa --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/BaseEntity.java @@ -0,0 +1,24 @@ +package org.yapp.domain; + + +import jakarta.persistence.Column; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.MappedSuperclass; +import java.time.LocalDateTime; +import lombok.Getter; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Getter +@MappedSuperclass +@EntityListeners(AuditingEntityListener.class) +public abstract class BaseEntity { + + @CreatedDate + @Column(updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + private LocalDateTime updatedAt; +} diff --git a/common/domain/src/main/java/org/yapp/domain/block/Block.java b/common/domain/src/main/java/org/yapp/domain/block/Block.java new file mode 100644 index 0000000..f1400b4 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/block/Block.java @@ -0,0 +1,46 @@ +package org.yapp.domain.block; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Index; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import jakarta.persistence.UniqueConstraint; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.user.User; + +@Entity +@Builder +@Getter +@AllArgsConstructor +@NoArgsConstructor +@Table(name = "blocked_contacts", + uniqueConstraints = { + @UniqueConstraint(name = "unq_user_phone", columnNames = {"user_id", "phoneNumber"}) + }, + indexes = { + @Index(name = "idx_phone_number", columnList = "phoneNumber"), + } +) +public class Block extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @Column(nullable = false) + private String phoneNumber; +} \ No newline at end of file diff --git a/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java b/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java new file mode 100644 index 0000000..f3cb759 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java @@ -0,0 +1,44 @@ +package org.yapp.domain.match; + +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 java.time.LocalDate; +import lombok.Getter; +import org.yapp.domain.user.User; + +@Entity +@Getter +public class MatchInfo { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "date") + private LocalDate date; + + @ManyToOne + @JoinColumn(name = "user_1") + private User user1; + + @Column(name = "user_1_piece_checked") + private Boolean user1PieceChecked; + + @Column(name = "user_1_accept") + private Boolean user1Accepted; + + @ManyToOne + @JoinColumn(name = "user_2") + private User user2; + + @Column(name = "user_2_piece_checked") + private Boolean user2PieceChecked; + + @Column(name = "user_2_accept") + private Boolean user2Accepted; +} diff --git a/common/domain/src/main/java/org/yapp/domain/profile/Profile.java b/common/domain/src/main/java/org/yapp/domain/profile/Profile.java new file mode 100644 index 0000000..87eda30 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/Profile.java @@ -0,0 +1,71 @@ +package org.yapp.domain.profile; + +import jakarta.persistence.CascadeType; +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; +import jakarta.persistence.OneToMany; +import jakarta.persistence.OneToOne; +import jakarta.persistence.Table; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.user.User; + +@Table(name = "profile") +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Profile extends BaseEntity { + + @Id + @Column(name = "profile_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne(mappedBy = "profile") + private User user; + + @Enumerated(EnumType.STRING) + @Builder.Default + private ProfileStatus status = ProfileStatus.INCOMPLETE; + + @Embedded + private ProfileBasic profileBasic; + + @Embedded + private ProfileBio profileBio; + + @OneToMany(mappedBy = "profile", cascade = CascadeType.ALL, orphanRemoval = true) + private List profileValueTalks; + + @OneToMany(mappedBy = "profile", cascade = CascadeType.ALL, orphanRemoval = true) + private List profileValuePicks; + + @Deprecated + public void updateBio(ProfileBio profileBio) { + this.profileBio = profileBio; + } + + public void updateBasic(ProfileBasic profileBasic) { + this.profileBasic = profileBasic; + } + + public void updateProfileValuePicks(List profileValuePicks) { + this.profileValuePicks = profileValuePicks; + } + + public void updateProfileValueTalks(List profileValueTalks) { + this.profileValueTalks = profileValueTalks; + } +} diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileBasic.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileBasic.java new file mode 100644 index 0000000..48b3c22 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileBasic.java @@ -0,0 +1,55 @@ +package org.yapp.domain.profile; + +import io.hypersistence.utils.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import java.time.LocalDate; +import java.util.Map; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Type; + +@Embeddable +@Getter +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@Builder +public class ProfileBasic { + + @Column(name = "nickname", nullable = false) + private String nickname; + + @Column(name = "description") + private String description; + + @Column(name = "birthdate") + private LocalDate birthdate; + + @Column(name = "height") + private Integer height; + + @Column(name = "job") + private String job; + + @Column(name = "location") + private String location; + + @Column(name = "smoking_status") + private String smokingStatus; + + @Column(name = "weight") + private Integer weight; + + @Column(name = "sns_activity_level") + private String snsActivityLevel; + + @Type(JsonType.class) + @Column(columnDefinition = "json") + private Map contacts; + + @Column(name = "image_url") + private String imageUrl; +} diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileBio.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileBio.java new file mode 100644 index 0000000..6b44c7b --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileBio.java @@ -0,0 +1,26 @@ +package org.yapp.domain.profile; + +import jakarta.persistence.Column; +import jakarta.persistence.Embeddable; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Deprecated +@Embeddable +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +@Builder +public class ProfileBio { + @Column(name = "introduction", length = 500) + private String introduction; + + @Column(name = "goal", length = 500) + private String goal; + + @Column(name = "interest", length = 500) + private String interest; +} \ No newline at end of file diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java new file mode 100644 index 0000000..392b4ae --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java @@ -0,0 +1,36 @@ +package org.yapp.domain.profile; + +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.OneToOne; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.user.User; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +@Getter +public class ProfileRejectHistory extends BaseEntity { + + @Id + @Column(name = "profile_reject_history_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne() + @JoinColumn(name = "user_id") + private User user; + + boolean reasonImage; + + boolean reasonDescription; +} diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileStatus.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileStatus.java new file mode 100644 index 0000000..1cfe51f --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileStatus.java @@ -0,0 +1,29 @@ +package org.yapp.domain.profile; + +public enum ProfileStatus { + + INCOMPLETE("미완료"), + REJECTED("보류"), + REVISED("수정 제출"), + APPROVED("통과"); + + private final String displayName; + + + ProfileStatus(String displayName) { + this.displayName = displayName; + } + + public String getDisplayName() { + return displayName; + } + + public static ProfileStatus fromDisplayName(String displayName) { + for (ProfileStatus status : ProfileStatus.values()) { + if (status.displayName.equals(displayName)) { + return status; + } + } + throw new IllegalArgumentException("Invalid display name: " + displayName); + } +} diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileValuePick.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileValuePick.java new file mode 100644 index 0000000..894da4a --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileValuePick.java @@ -0,0 +1,53 @@ +package org.yapp.domain.profile; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.value.ValuePick; + +@Entity +@Table(name = "profile_value_pick") +@Getter +@NoArgsConstructor +public class ProfileValuePick { + + @Id + @Column(name = "profile_value_pick_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "profile_id", nullable = false) + private Profile profile; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "value_pick_id", nullable = false) + private ValuePick valuePick; + + @Column + private Integer selectedAnswer; + + @Builder + public ProfileValuePick(Profile profile, ValuePick valuePick, Integer selectedAnswer) { + this.profile = profile; + this.valuePick = valuePick; + this.selectedAnswer = selectedAnswer; + } + + public void updatedSelectedAnswer(Integer newSelectedAnswer) { + if (newSelectedAnswer == null || newSelectedAnswer <= 0) { + throw new IllegalArgumentException("선택된 항목은 1 이상이어야 합니다."); + } + + this.selectedAnswer = newSelectedAnswer; + } +} diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java new file mode 100644 index 0000000..ebd8067 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java @@ -0,0 +1,52 @@ +package org.yapp.domain.profile; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.value.ValueTalk; + +@Entity +@Table(name = "profile_value_talk") +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ProfileValueTalk { + + @Id + @Column(name = "profile_value_talk_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "profile_id", nullable = false) + private Profile profile; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "value_talk_id", nullable = false) + private ValueTalk valueTalk; + + @Column + private String summary; + + @Column(length = 300) + private String answer; + + public void updateAnswer(String answer) { + this.answer = answer; + } + + public void updateSummary(String summary) { + this.summary = summary; + } +} \ No newline at end of file diff --git a/common/domain/src/main/java/org/yapp/domain/term/Term.java b/common/domain/src/main/java/org/yapp/domain/term/Term.java new file mode 100644 index 0000000..62092ee --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/term/Term.java @@ -0,0 +1,41 @@ +package org.yapp.domain.term; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Term { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "term_id") + private long id; + + private String version; + + private String title; + + private String content; + + @Column(nullable = false) + private boolean required; + + @Column(nullable = false) + private LocalDateTime startDate; + + @ColumnDefault(value = "true") + private boolean isActive; +} diff --git a/common/domain/src/main/java/org/yapp/domain/term/TermAgreement.java b/common/domain/src/main/java/org/yapp/domain/term/TermAgreement.java new file mode 100644 index 0000000..1e443db --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/term/TermAgreement.java @@ -0,0 +1,40 @@ +package org.yapp.domain.term; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.JoinColumn; +import jakarta.persistence.ManyToOne; +import java.time.LocalDateTime; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.user.User; + +@Entity +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class TermAgreement { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "agreement_id") + private long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "user_id", nullable = false) + private User user; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name = "term_id", nullable = false) + private Term term; + + @Column(nullable = false) + private LocalDateTime agreedAt; +} diff --git a/common/domain/src/main/java/org/yapp/domain/user/User.java b/common/domain/src/main/java/org/yapp/domain/user/User.java new file mode 100644 index 0000000..04ebaf2 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/user/User.java @@ -0,0 +1,59 @@ +package org.yapp.domain.user; + +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.OneToOne; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.profile.Profile; + +@Table(name = "user_table") +@Entity +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class User extends BaseEntity { + + @Id + @Column(name = "user_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "oauth_id") + private String oauthId; + + @Column(name = "name") + private String name; + + @Column(name = "phone") + private String phoneNumber; + + @Column(name = "role") + private String role; + + @OneToOne + @JoinColumn(name = "profile_id", unique = true) // User가 profile_id를 FK로 가짐 + private Profile profile; + + public void initializePhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + public void setProfile(Profile profile) { + this.profile = profile; + } + + public void updateUserRole(String role) { + this.role = role; + } +} + diff --git a/common/domain/src/main/java/org/yapp/domain/value/ValuePick.java b/common/domain/src/main/java/org/yapp/domain/value/ValuePick.java new file mode 100644 index 0000000..86be7a5 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/value/ValuePick.java @@ -0,0 +1,42 @@ +package org.yapp.domain.value; + +import io.hypersistence.utils.hibernate.type.json.JsonType; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.util.Map; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.Type; + +@Entity +@Table(name = "value_pick") +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ValuePick { + + @Id + @Column(name = "value_pick_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column + private String category; + + @Column(nullable = false) + private String question; + + @Column(nullable = false) + private boolean isActive = true; + + @Type(JsonType.class) + @Column(name = "answers", columnDefinition = "longtext", nullable = false) + private Map answers; +} diff --git a/common/domain/src/main/java/org/yapp/domain/value/ValueTalk.java b/common/domain/src/main/java/org/yapp/domain/value/ValueTalk.java new file mode 100644 index 0000000..b0e4282 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/value/ValueTalk.java @@ -0,0 +1,40 @@ +package org.yapp.domain.value; + +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; + +@Entity +@Table(name = "value_talk") +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class ValueTalk { + + @Id + @Column(name = "value_talk_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column + private String category; + + @Column(nullable = false) + private String title; + + @Column + private String guide; + + @Column(nullable = false) + @ColumnDefault("true") + private boolean isActive; +} From d00b2c264d8b7c5ca7e75659214a3693e7bceecd Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 14:59:36 +0900 Subject: [PATCH 06/38] =?UTF-8?q?[PC-380]=20refactor:=20common:domain=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yapp/error/GlobalExceptionHandler.java | 100 ++++++++++++++++++ .../yapp/error/code/auth/AuthErrorCode.java | 16 +++ .../error/code/auth/SmsAuthErrorCode.java | 15 +++ .../org/yapp/error/dto/CommonErrorCode.java | 23 ++++ .../java/org/yapp/error/dto/ErrorCode.java | 9 ++ .../org/yapp/error/dto/ErrorResponse.java | 36 +++++++ .../org/yapp/error/dto/MatchErrorCode.java | 15 +++ .../org/yapp/error/dto/ProfileErrorCode.java | 16 +++ .../org/yapp/error/dto/SecurityErrorCode.java | 30 ++++++ .../org/yapp/error/dto/TermErrorCode.java | 17 +++ .../error/exception/ApplicationException.java | 12 +++ 11 files changed, 289 insertions(+) create mode 100644 common/exception/src/main/java/org/yapp/error/GlobalExceptionHandler.java create mode 100644 common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/code/auth/SmsAuthErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/CommonErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/ErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/ErrorResponse.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/MatchErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/SecurityErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/TermErrorCode.java create mode 100644 common/exception/src/main/java/org/yapp/error/exception/ApplicationException.java diff --git a/common/exception/src/main/java/org/yapp/error/GlobalExceptionHandler.java b/common/exception/src/main/java/org/yapp/error/GlobalExceptionHandler.java new file mode 100644 index 0000000..6161dda --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/GlobalExceptionHandler.java @@ -0,0 +1,100 @@ +package org.yapp.error; + +import java.util.List; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatusCode; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.BindException; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.RestControllerAdvice; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; +import org.yapp.error.dto.CommonErrorCode; +import org.yapp.error.dto.ErrorCode; +import org.yapp.error.dto.ErrorResponse; +import org.yapp.error.exception.ApplicationException; + + +@RestControllerAdvice +@Slf4j +public class GlobalExceptionHandler extends ResponseEntityExceptionHandler { + + @ExceptionHandler(ApplicationException.class) + public ResponseEntity handleQuizException(final ApplicationException e) { + final ErrorCode errorCode = e.getErrorCode(); + return handleExceptionInternal(errorCode); + } + + @ExceptionHandler(IllegalArgumentException.class) + public ResponseEntity handleIllegalArgument(final IllegalArgumentException e) { + log.warn("handleIllegalArgument", e); + final ErrorCode errorCode = CommonErrorCode.INVALID_PARAMETER; + return handleExceptionInternal(errorCode, e.getMessage()); + } + + @Override + public ResponseEntity handleMethodArgumentNotValid( + final MethodArgumentNotValidException e, + final HttpHeaders headers, + final HttpStatusCode status, + final WebRequest request) { + log.warn("handleIllegalArgument", e); + final ErrorCode errorCode = CommonErrorCode.INVALID_PARAMETER; + return handleExceptionInternal(e, errorCode); + } + + @ExceptionHandler({Exception.class}) + public ResponseEntity handleAllException(final Exception ex) { + log.warn("handleAllException", ex); + final ErrorCode errorCode = CommonErrorCode.INTERNAL_SERVER_ERROR; + return handleExceptionInternal(errorCode); + } + + private ResponseEntity handleExceptionInternal(final ErrorCode errorCode) { + return ResponseEntity.status(errorCode.getHttpStatus()) + .body(makeErrorResponse(errorCode)); + } + + private ResponseEntity handleExceptionInternal(final ErrorCode errorCode, + final String message) { + return ResponseEntity.status(errorCode.getHttpStatus()) + .body(makeErrorResponse(errorCode, message)); + } + + private ResponseEntity handleExceptionInternal(final BindException e, + final ErrorCode errorCode) { + return ResponseEntity.status(errorCode.getHttpStatus()) + .body(makeErrorResponse(e, errorCode)); + } + + private ErrorResponse makeErrorResponse(final ErrorCode errorCode) { + return ErrorResponse.builder() + .code(errorCode.name()) + .message(errorCode.getMessage()) + .build(); + } + + private ErrorResponse makeErrorResponse(final ErrorCode errorCode, final String message) { + return ErrorResponse.builder() + .code(errorCode.name()) + .message(message) + .build(); + } + + private ErrorResponse makeErrorResponse(final BindException e, final ErrorCode errorCode) { + final List validationErrorList = e.getBindingResult() + .getFieldErrors() + .stream() + .map(ErrorResponse.ValidationError::of) + .collect(Collectors.toList()); + + return ErrorResponse.builder() + .code(errorCode.name()) + .message(errorCode.getMessage()) + .errors(validationErrorList) + .build(); + } +} \ No newline at end of file diff --git a/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java b/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java new file mode 100644 index 0000000..0b01dfb --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java @@ -0,0 +1,16 @@ +package org.yapp.error.code.auth; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.yapp.error.dto.ErrorCode; + +@Getter +@RequiredArgsConstructor +public enum AuthErrorCode implements ErrorCode { + OAUTH_ERROR(HttpStatus.FORBIDDEN, "Oauth Error"), + ; + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/code/auth/SmsAuthErrorCode.java b/common/exception/src/main/java/org/yapp/error/code/auth/SmsAuthErrorCode.java new file mode 100644 index 0000000..122f81f --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/code/auth/SmsAuthErrorCode.java @@ -0,0 +1,15 @@ +package org.yapp.error.code.auth; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.yapp.error.dto.ErrorCode; + +@Getter +@RequiredArgsConstructor +public enum SmsAuthErrorCode implements ErrorCode { + CODE_NOT_EXIST(HttpStatus.BAD_REQUEST, "code not exist"), + CODE_NOT_CORRECT(HttpStatus.BAD_REQUEST, "code not correct"); + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/CommonErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/CommonErrorCode.java new file mode 100644 index 0000000..1f8a1ee --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/CommonErrorCode.java @@ -0,0 +1,23 @@ +package org.yapp.error.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum CommonErrorCode implements ErrorCode{ + // 400 BAD_REQUEST + INVALID_PARAMETER(HttpStatus.BAD_REQUEST, "Invalid parameter included"), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "Authentication required"), + FORBIDDEN(HttpStatus.FORBIDDEN, "You do not have permission to access this resource"), + + // 404 NOT_FOUND + RESOURCE_NOT_FOUND(HttpStatus.NOT_FOUND, "Resource not found"), + + // 500 INTERNAL_SERVER_ERROR + INTERNAL_SERVER_ERROR(HttpStatus.INTERNAL_SERVER_ERROR, "Internal server error"); + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/ErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/ErrorCode.java new file mode 100644 index 0000000..0ec5cf7 --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/ErrorCode.java @@ -0,0 +1,9 @@ +package org.yapp.error.dto; + +import org.springframework.http.HttpStatus; + +public interface ErrorCode { + String name(); + HttpStatus getHttpStatus(); + String getMessage(); +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/ErrorResponse.java b/common/exception/src/main/java/org/yapp/error/dto/ErrorResponse.java new file mode 100644 index 0000000..87099b9 --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/ErrorResponse.java @@ -0,0 +1,36 @@ +package org.yapp.error.dto; + +import com.fasterxml.jackson.annotation.JsonInclude; +import java.util.List; +import lombok.Builder; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.validation.FieldError; + +@Getter +@Builder +@RequiredArgsConstructor +public class ErrorResponse { + + private final String code; + private final String message; + + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private final List errors; + + @Getter + @Builder + @RequiredArgsConstructor + public static class ValidationError { + + private final String field; + private final String message; + + public static ValidationError of(final FieldError fieldError) { + return ValidationError.builder() + .field(fieldError.getField()) + .message(fieldError.getDefaultMessage()) + .build(); + } + } +} \ No newline at end of file diff --git a/common/exception/src/main/java/org/yapp/error/dto/MatchErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/MatchErrorCode.java new file mode 100644 index 0000000..ca14e0b --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/MatchErrorCode.java @@ -0,0 +1,15 @@ +package org.yapp.error.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum MatchErrorCode implements ErrorCode { + NOTFOUND_MATCH(HttpStatus.NOT_FOUND, "Match not found"), + ; + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java new file mode 100644 index 0000000..6ec0c44 --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java @@ -0,0 +1,16 @@ +package org.yapp.error.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum ProfileErrorCode implements ErrorCode { + INACTIVE_PROFILE(HttpStatus.FORBIDDEN, "Profile is inactive"), + NOTFOUND_PROFILE(HttpStatus.NOT_FOUND, "Profile not found"), + ; + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/SecurityErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/SecurityErrorCode.java new file mode 100644 index 0000000..e842d1d --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/SecurityErrorCode.java @@ -0,0 +1,30 @@ +package org.yapp.error.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum SecurityErrorCode implements ErrorCode { + // Authentication Errors + MISSING_ACCESS_TOKEN(HttpStatus.BAD_REQUEST, "Access token is missing."), + INVALID_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "Invalid access token."), + EXPIRED_ACCESS_TOKEN(HttpStatus.UNAUTHORIZED, "Access token has expired."), + + MISSING_REFRESH_TOKEN(HttpStatus.BAD_REQUEST, "Refresh token is missing."), + INVALID_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "Invalid refresh token."), + EXPIRED_REFRESH_TOKEN(HttpStatus.UNAUTHORIZED, "Refresh token has expired."), + + INVALID_AUTHORIZATION_HEADER(HttpStatus.BAD_REQUEST, "Authorization header is invalid."), + UNSUPPORTED_TOKEN(HttpStatus.UNAUTHORIZED, "Unsupported token format."), + INVALID_JWT_SIGNATURE(HttpStatus.UNAUTHORIZED, "Invalid JWT signature."), + + // Authorization Errors + ACCESS_DENIED(HttpStatus.FORBIDDEN, "Access is denied."), + ROLE_NOT_ALLOWED(HttpStatus.FORBIDDEN, "User does not have the required role to access this resource."), + ; + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/TermErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/TermErrorCode.java new file mode 100644 index 0000000..dd46507 --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/TermErrorCode.java @@ -0,0 +1,17 @@ +package org.yapp.error.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum TermErrorCode implements ErrorCode { + INACTIVE_TERM(HttpStatus.FORBIDDEN, "접근이 금지된 약관입니다."), + NOTFOUND_TERM(HttpStatus.NOT_FOUND, "유효하지 않은 약관입니다."), + NOT_REQUIRED_TERM(HttpStatus.BAD_REQUEST, "모든 필수 약관을 동의해야합니다.") + ; + + private final HttpStatus httpStatus; + private final String message; +} diff --git a/common/exception/src/main/java/org/yapp/error/exception/ApplicationException.java b/common/exception/src/main/java/org/yapp/error/exception/ApplicationException.java new file mode 100644 index 0000000..7fab0ee --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/exception/ApplicationException.java @@ -0,0 +1,12 @@ +package org.yapp.error.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.yapp.error.dto.ErrorCode; + +@Getter +@RequiredArgsConstructor +public class ApplicationException extends RuntimeException { + + private final ErrorCode errorCode; +} From fcae56e4b0254f1b573ed40f6471e670eacbffad Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 15:01:11 +0900 Subject: [PATCH 07/38] =?UTF-8?q?[PC-380]=20refactor:=20common:domain=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/src/main/java/org/yapp/config/JpaConfig.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 common/domain/src/main/java/org/yapp/config/JpaConfig.java diff --git a/common/domain/src/main/java/org/yapp/config/JpaConfig.java b/common/domain/src/main/java/org/yapp/config/JpaConfig.java new file mode 100644 index 0000000..7f7f0e6 --- /dev/null +++ b/common/domain/src/main/java/org/yapp/config/JpaConfig.java @@ -0,0 +1,9 @@ +package org.yapp.config; + +import org.springframework.context.annotation.Configuration; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; + +@Configuration +@EnableJpaAuditing +public class JpaConfig { +} \ No newline at end of file From 32cc85e8d8bc77c570c7b201ee29aa38d867bb8d Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 15:33:51 +0900 Subject: [PATCH 08/38] =?UTF-8?q?[PC-380]=20refactor:=20common=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=EC=97=90=EC=84=9C=20domain=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=84=B8=EB=B6=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/build.gradle | 1 + .../main/java/org/yapp/domain/BaseEntity.java | 25 ------- .../java/org/yapp/domain/block/Block.java | 35 --------- .../java/org/yapp/domain/match/MatchInfo.java | 45 ------------ .../java/org/yapp/domain/profile/Profile.java | 71 ------------------- .../org/yapp/domain/profile/ProfileBasic.java | 55 -------------- .../org/yapp/domain/profile/ProfileBio.java | 26 ------- .../domain/profile/ProfileRejectHistory.java | 34 --------- .../yapp/domain/profile/ProfileStatus.java | 29 -------- .../yapp/domain/profile/ProfileValuePick.java | 52 -------------- .../yapp/domain/profile/ProfileValueTalk.java | 52 -------------- .../main/java/org/yapp/domain/term/Term.java | 37 ---------- .../org/yapp/domain/term/TermAgreement.java | 33 --------- .../main/java/org/yapp/domain/user/User.java | 59 --------------- .../java/org/yapp/domain/value/ValuePick.java | 42 ----------- .../java/org/yapp/domain/value/ValueTalk.java | 40 ----------- 16 files changed, 1 insertion(+), 635 deletions(-) delete mode 100644 common/src/main/java/org/yapp/domain/BaseEntity.java delete mode 100644 common/src/main/java/org/yapp/domain/block/Block.java delete mode 100644 common/src/main/java/org/yapp/domain/match/MatchInfo.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/Profile.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileBasic.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileBio.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileStatus.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileValuePick.java delete mode 100644 common/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java delete mode 100644 common/src/main/java/org/yapp/domain/term/Term.java delete mode 100644 common/src/main/java/org/yapp/domain/term/TermAgreement.java delete mode 100644 common/src/main/java/org/yapp/domain/user/User.java delete mode 100644 common/src/main/java/org/yapp/domain/value/ValuePick.java delete mode 100644 common/src/main/java/org/yapp/domain/value/ValueTalk.java diff --git a/api/build.gradle b/api/build.gradle index 67731b8..9c52b61 100644 --- a/api/build.gradle +++ b/api/build.gradle @@ -11,6 +11,7 @@ repositories { dependencies { implementation project(':common') + implementation project(':common:domain') testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' diff --git a/common/src/main/java/org/yapp/domain/BaseEntity.java b/common/src/main/java/org/yapp/domain/BaseEntity.java deleted file mode 100644 index 4752f1f..0000000 --- a/common/src/main/java/org/yapp/domain/BaseEntity.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.yapp.domain; - - -import jakarta.persistence.Column; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.MappedSuperclass; -import lombok.Getter; -import org.springframework.data.annotation.CreatedDate; -import org.springframework.data.annotation.LastModifiedDate; -import org.springframework.data.jpa.domain.support.AuditingEntityListener; - -import java.time.LocalDateTime; - -@Getter -@MappedSuperclass -@EntityListeners(AuditingEntityListener.class) -public abstract class BaseEntity { - - @CreatedDate - @Column(updatable = false) - private LocalDateTime createdAt; - - @LastModifiedDate - private LocalDateTime updatedAt; -} diff --git a/common/src/main/java/org/yapp/domain/block/Block.java b/common/src/main/java/org/yapp/domain/block/Block.java deleted file mode 100644 index e91670a..0000000 --- a/common/src/main/java/org/yapp/domain/block/Block.java +++ /dev/null @@ -1,35 +0,0 @@ -package org.yapp.domain.block; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.yapp.domain.BaseEntity; -import org.yapp.domain.user.User; - -@Entity -@Builder -@Getter -@AllArgsConstructor -@NoArgsConstructor -@Table(name = "blocked_contacts", - uniqueConstraints = { - @UniqueConstraint(name = "unq_user_phone", columnNames = {"user_id", "phoneNumber"}) - }, - indexes = { - @Index(name = "idx_phone_number", columnList = "phoneNumber"), - } -) -public class Block extends BaseEntity { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id", nullable = false) - private User user; - - @Column(nullable = false) - private String phoneNumber; -} \ No newline at end of file diff --git a/common/src/main/java/org/yapp/domain/match/MatchInfo.java b/common/src/main/java/org/yapp/domain/match/MatchInfo.java deleted file mode 100644 index e66f86e..0000000 --- a/common/src/main/java/org/yapp/domain/match/MatchInfo.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.yapp.domain.match; - -import org.yapp.domain.user.User; - -import java.time.LocalDate; - -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.Getter; - -@Entity -@Getter -public class MatchInfo { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "date") - private LocalDate date; - - @ManyToOne - @JoinColumn(name = "user_1") - private User user1; - - @Column(name = "user_1_piece_checked") - private Boolean user1PieceChecked; - - @Column(name = "user_1_accept") - private Boolean user1Accepted; - - @ManyToOne - @JoinColumn(name = "user_2") - private User user2; - - @Column(name = "user_2_piece_checked") - private Boolean user2PieceChecked; - - @Column(name = "user_2_accept") - private Boolean user2Accepted; -} diff --git a/common/src/main/java/org/yapp/domain/profile/Profile.java b/common/src/main/java/org/yapp/domain/profile/Profile.java deleted file mode 100644 index 87eda30..0000000 --- a/common/src/main/java/org/yapp/domain/profile/Profile.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.yapp.domain.profile; - -import jakarta.persistence.CascadeType; -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; -import jakarta.persistence.OneToMany; -import jakarta.persistence.OneToOne; -import jakarta.persistence.Table; -import java.util.List; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.yapp.domain.BaseEntity; -import org.yapp.domain.user.User; - -@Table(name = "profile") -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class Profile extends BaseEntity { - - @Id - @Column(name = "profile_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne(mappedBy = "profile") - private User user; - - @Enumerated(EnumType.STRING) - @Builder.Default - private ProfileStatus status = ProfileStatus.INCOMPLETE; - - @Embedded - private ProfileBasic profileBasic; - - @Embedded - private ProfileBio profileBio; - - @OneToMany(mappedBy = "profile", cascade = CascadeType.ALL, orphanRemoval = true) - private List profileValueTalks; - - @OneToMany(mappedBy = "profile", cascade = CascadeType.ALL, orphanRemoval = true) - private List profileValuePicks; - - @Deprecated - public void updateBio(ProfileBio profileBio) { - this.profileBio = profileBio; - } - - public void updateBasic(ProfileBasic profileBasic) { - this.profileBasic = profileBasic; - } - - public void updateProfileValuePicks(List profileValuePicks) { - this.profileValuePicks = profileValuePicks; - } - - public void updateProfileValueTalks(List profileValueTalks) { - this.profileValueTalks = profileValueTalks; - } -} diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileBasic.java b/common/src/main/java/org/yapp/domain/profile/ProfileBasic.java deleted file mode 100644 index 48b3c22..0000000 --- a/common/src/main/java/org/yapp/domain/profile/ProfileBasic.java +++ /dev/null @@ -1,55 +0,0 @@ -package org.yapp.domain.profile; - -import io.hypersistence.utils.hibernate.type.json.JsonType; -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import java.time.LocalDate; -import java.util.Map; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; - -@Embeddable -@Getter -@AllArgsConstructor -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@Builder -public class ProfileBasic { - - @Column(name = "nickname", nullable = false) - private String nickname; - - @Column(name = "description") - private String description; - - @Column(name = "birthdate") - private LocalDate birthdate; - - @Column(name = "height") - private Integer height; - - @Column(name = "job") - private String job; - - @Column(name = "location") - private String location; - - @Column(name = "smoking_status") - private String smokingStatus; - - @Column(name = "weight") - private Integer weight; - - @Column(name = "sns_activity_level") - private String snsActivityLevel; - - @Type(JsonType.class) - @Column(columnDefinition = "json") - private Map contacts; - - @Column(name = "image_url") - private String imageUrl; -} diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileBio.java b/common/src/main/java/org/yapp/domain/profile/ProfileBio.java deleted file mode 100644 index 6b44c7b..0000000 --- a/common/src/main/java/org/yapp/domain/profile/ProfileBio.java +++ /dev/null @@ -1,26 +0,0 @@ -package org.yapp.domain.profile; - -import jakarta.persistence.Column; -import jakarta.persistence.Embeddable; -import lombok.AccessLevel; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Deprecated -@Embeddable -@Getter -@NoArgsConstructor(access = AccessLevel.PROTECTED) -@AllArgsConstructor -@Builder -public class ProfileBio { - @Column(name = "introduction", length = 500) - private String introduction; - - @Column(name = "goal", length = 500) - private String goal; - - @Column(name = "interest", length = 500) - private String interest; -} \ No newline at end of file diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java b/common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java deleted file mode 100644 index 727d692..0000000 --- a/common/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java +++ /dev/null @@ -1,34 +0,0 @@ -package org.yapp.domain.profile; - -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.OneToOne; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.NoArgsConstructor; -import org.yapp.domain.BaseEntity; -import org.yapp.domain.user.User; - -@Entity -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ProfileRejectHistory extends BaseEntity { - - @Id - @Column(name = "profile_reject_history_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @OneToOne() - @JoinColumn(name = "user_id") - private User user; - - boolean reasonImage; - - boolean reasonDescription; -} diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileStatus.java b/common/src/main/java/org/yapp/domain/profile/ProfileStatus.java deleted file mode 100644 index 1cfe51f..0000000 --- a/common/src/main/java/org/yapp/domain/profile/ProfileStatus.java +++ /dev/null @@ -1,29 +0,0 @@ -package org.yapp.domain.profile; - -public enum ProfileStatus { - - INCOMPLETE("미완료"), - REJECTED("보류"), - REVISED("수정 제출"), - APPROVED("통과"); - - private final String displayName; - - - ProfileStatus(String displayName) { - this.displayName = displayName; - } - - public String getDisplayName() { - return displayName; - } - - public static ProfileStatus fromDisplayName(String displayName) { - for (ProfileStatus status : ProfileStatus.values()) { - if (status.displayName.equals(displayName)) { - return status; - } - } - throw new IllegalArgumentException("Invalid display name: " + displayName); - } -} diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileValuePick.java b/common/src/main/java/org/yapp/domain/profile/ProfileValuePick.java deleted file mode 100644 index 037340c..0000000 --- a/common/src/main/java/org/yapp/domain/profile/ProfileValuePick.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.yapp.domain.profile; - -import org.yapp.domain.value.ValuePick; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Entity -@Table(name = "profile_value_pick") -@Getter -@NoArgsConstructor -public class ProfileValuePick { - @Id - @Column(name = "profile_value_pick_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "profile_id", nullable = false) - private Profile profile; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "value_pick_id", nullable = false) - private ValuePick valuePick; - - @Column - private Integer selectedAnswer; - - @Builder - public ProfileValuePick(Profile profile, ValuePick valuePick, Integer selectedAnswer) { - this.profile = profile; - this.valuePick = valuePick; - this.selectedAnswer = selectedAnswer; - } - - public void updatedSelectedAnswer(Integer newSelectedAnswer) { - if (newSelectedAnswer == null || newSelectedAnswer <= 0) - throw new IllegalArgumentException("선택된 항목은 1 이상이어야 합니다."); - - this.selectedAnswer = newSelectedAnswer; - } -} diff --git a/common/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java b/common/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java deleted file mode 100644 index ebd8067..0000000 --- a/common/src/main/java/org/yapp/domain/profile/ProfileValueTalk.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.yapp.domain.profile; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.FetchType; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.JoinColumn; -import jakarta.persistence.ManyToOne; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.yapp.domain.value.ValueTalk; - -@Entity -@Table(name = "profile_value_talk") -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ProfileValueTalk { - - @Id - @Column(name = "profile_value_talk_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "profile_id", nullable = false) - private Profile profile; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "value_talk_id", nullable = false) - private ValueTalk valueTalk; - - @Column - private String summary; - - @Column(length = 300) - private String answer; - - public void updateAnswer(String answer) { - this.answer = answer; - } - - public void updateSummary(String summary) { - this.summary = summary; - } -} \ No newline at end of file diff --git a/common/src/main/java/org/yapp/domain/term/Term.java b/common/src/main/java/org/yapp/domain/term/Term.java deleted file mode 100644 index e0ac2a1..0000000 --- a/common/src/main/java/org/yapp/domain/term/Term.java +++ /dev/null @@ -1,37 +0,0 @@ -package org.yapp.domain.term; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; - -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class Term { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "term_id") - private long id; - - private String version; - - private String title; - - private String content; - - @Column(nullable = false) - private boolean required; - - @Column(nullable = false) - private LocalDateTime startDate; - - @ColumnDefault(value = "true") - private boolean isActive; -} diff --git a/common/src/main/java/org/yapp/domain/term/TermAgreement.java b/common/src/main/java/org/yapp/domain/term/TermAgreement.java deleted file mode 100644 index 2ae9f7c..0000000 --- a/common/src/main/java/org/yapp/domain/term/TermAgreement.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.yapp.domain.term; - -import jakarta.persistence.*; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.yapp.domain.user.User; - -import java.time.LocalDateTime; - -@Entity -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class TermAgreement { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - @Column(name = "agreement_id") - private long id; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "user_id", nullable = false) - private User user; - - @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "term_id", nullable = false) - private Term term; - - @Column(nullable = false) - private LocalDateTime agreedAt; -} diff --git a/common/src/main/java/org/yapp/domain/user/User.java b/common/src/main/java/org/yapp/domain/user/User.java deleted file mode 100644 index d712e6f..0000000 --- a/common/src/main/java/org/yapp/domain/user/User.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.yapp.domain.user; - -import org.yapp.domain.profile.Profile; - -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.OneToOne; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@Table(name = "user_table") -@Entity -@Getter -@Builder -@AllArgsConstructor -@NoArgsConstructor -public class User { - - @Id - @Column(name = "user_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column(name = "oauth_id") - private String oauthId; - - @Column(name = "name") - private String name; - - @Column(name = "phone") - private String phoneNumber; - - @Column(name = "role") - private String role; - - @OneToOne - @JoinColumn(name = "profile_id", unique = true) // User가 profile_id를 FK로 가짐 - private Profile profile; - - public void initializePhoneNumber(String phoneNumber) { - this.phoneNumber = phoneNumber; - } - - public void setProfile(Profile profile) { - this.profile = profile; - } - - public void updateUserRole(String role) { - this.role = role; - } -} - diff --git a/common/src/main/java/org/yapp/domain/value/ValuePick.java b/common/src/main/java/org/yapp/domain/value/ValuePick.java deleted file mode 100644 index 86be7a5..0000000 --- a/common/src/main/java/org/yapp/domain/value/ValuePick.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.yapp.domain.value; - -import io.hypersistence.utils.hibernate.type.json.JsonType; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import java.util.Map; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.Type; - -@Entity -@Table(name = "value_pick") -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ValuePick { - - @Id - @Column(name = "value_pick_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column - private String category; - - @Column(nullable = false) - private String question; - - @Column(nullable = false) - private boolean isActive = true; - - @Type(JsonType.class) - @Column(name = "answers", columnDefinition = "longtext", nullable = false) - private Map answers; -} diff --git a/common/src/main/java/org/yapp/domain/value/ValueTalk.java b/common/src/main/java/org/yapp/domain/value/ValueTalk.java deleted file mode 100644 index b0e4282..0000000 --- a/common/src/main/java/org/yapp/domain/value/ValueTalk.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.yapp.domain.value; - -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; - -@Entity -@Table(name = "value_talk") -@Getter -@NoArgsConstructor -@AllArgsConstructor -@Builder -public class ValueTalk { - - @Id - @Column(name = "value_talk_id") - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - - @Column - private String category; - - @Column(nullable = false) - private String title; - - @Column - private String guide; - - @Column(nullable = false) - @ColumnDefault("true") - private boolean isActive; -} From 0e13af3f7467d56244db5025eeeec3c047648154 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 15:38:59 +0900 Subject: [PATCH 09/38] =?UTF-8?q?[PC-380]=20fix:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=83=81=ED=83=9C=20=EC=BB=AC=EB=9F=BC=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/src/main/java/org/yapp/domain/profile/Profile.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/domain/src/main/java/org/yapp/domain/profile/Profile.java b/common/domain/src/main/java/org/yapp/domain/profile/Profile.java index 87eda30..df1b562 100644 --- a/common/domain/src/main/java/org/yapp/domain/profile/Profile.java +++ b/common/domain/src/main/java/org/yapp/domain/profile/Profile.java @@ -38,7 +38,7 @@ public class Profile extends BaseEntity { @Enumerated(EnumType.STRING) @Builder.Default - private ProfileStatus status = ProfileStatus.INCOMPLETE; + private ProfileStatus profileStatus = ProfileStatus.INCOMPLETE; @Embedded private ProfileBasic profileBasic; From aff12cee356e929e36ff6ccddc5ba4616d2f057e Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 16:13:04 +0900 Subject: [PATCH 10/38] =?UTF-8?q?[PC-000]=20chore:=20=EC=BB=A8=EB=B2=A4?= =?UTF-8?q?=EC=85=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yapp/domain/user/dao/UserRepository.java | 2 +- .../yapp/global/application/RedisService.java | 26 +++++++++---------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/api/src/main/java/org/yapp/domain/user/dao/UserRepository.java b/api/src/main/java/org/yapp/domain/user/dao/UserRepository.java index 7cc581b..52741d6 100644 --- a/api/src/main/java/org/yapp/domain/user/dao/UserRepository.java +++ b/api/src/main/java/org/yapp/domain/user/dao/UserRepository.java @@ -6,5 +6,5 @@ import java.util.Optional; public interface UserRepository extends JpaRepository { - Optional findByOauthId(String oauthId); + Optional findByOauthId(String oauthId); } diff --git a/api/src/main/java/org/yapp/global/application/RedisService.java b/api/src/main/java/org/yapp/global/application/RedisService.java index 0da05cb..a33ff12 100644 --- a/api/src/main/java/org/yapp/global/application/RedisService.java +++ b/api/src/main/java/org/yapp/global/application/RedisService.java @@ -1,27 +1,25 @@ package org.yapp.global.application; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.stereotype.Service; - import java.time.Duration; - import lombok.RequiredArgsConstructor; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class RedisService { - private final StringRedisTemplate redisTemplate; + private final StringRedisTemplate redisTemplate; - public void deleteKey(String key) { - redisTemplate.delete(key); - } + public void deleteKey(String key) { + redisTemplate.delete(key); + } - public String getValue(String key) { - return redisTemplate.opsForValue().get(key); - } + public String getValue(String key) { + return redisTemplate.opsForValue().get(key); + } - public void setKeyWithExpiration(String key, String value, long expiredTime) { - redisTemplate.opsForValue().set(key, value, Duration.ofMillis(expiredTime)); - } + public void setKeyWithExpiration(String key, String value, long expiredTime) { + redisTemplate.opsForValue().set(key, value, Duration.ofMillis(expiredTime)); + } } From 2287031e3d26653ad57165edfa474d5139a2887f Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 16:13:36 +0900 Subject: [PATCH 11/38] =?UTF-8?q?[PC-000]=20refactor:=20=EB=AA=A8=EB=93=88?= =?UTF-8?q?=20=EC=84=B8=EB=B6=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/build.gradle | 4 ++++ common/domain/build.gradle | 22 ++++++++++++++++++++++ common/exception/build.gradle | 19 +++++++++++++++++++ common/format/build.gradle | 19 +++++++++++++++++++ settings.gradle | 6 ++++++ 5 files changed, 70 insertions(+) create mode 100644 common/domain/build.gradle create mode 100644 common/exception/build.gradle create mode 100644 common/format/build.gradle diff --git a/admin/build.gradle b/admin/build.gradle index fda8bf5..5c74e14 100644 --- a/admin/build.gradle +++ b/admin/build.gradle @@ -10,6 +10,10 @@ repositories { } dependencies { + implementation project(':common:domain') + implementation project(':common:format') + implementation project(':common:exception') + testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' } diff --git a/common/domain/build.gradle b/common/domain/build.gradle new file mode 100644 index 0000000..288bf73 --- /dev/null +++ b/common/domain/build.gradle @@ -0,0 +1,22 @@ +plugins { + id 'java' +} + +group = 'org.yapp' +version = '0.0.1-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + implementation('io.hypersistence:hypersistence-utils-hibernate-62:3.7.0') + + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/common/exception/build.gradle b/common/exception/build.gradle new file mode 100644 index 0000000..fda8bf5 --- /dev/null +++ b/common/exception/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +group = 'org.yapp' +version = '0.0.1-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/common/format/build.gradle b/common/format/build.gradle new file mode 100644 index 0000000..fda8bf5 --- /dev/null +++ b/common/format/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +group = 'org.yapp' +version = '0.0.1-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file diff --git a/settings.gradle b/settings.gradle index 6d789cb..d3c3d28 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,4 +2,10 @@ rootProject.name = 'dating-match' include 'api' include 'admin' include 'common' +include 'common:domain' +findProject(':common:domain')?.name = 'domain' +include 'common:exception' +findProject(':common:exception')?.name = 'exception' +include 'common:format' +findProject(':common:format')?.name = 'format' From 7ced203945e20ad58823c4fd8757cb6297b8d8fe Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 16:14:04 +0900 Subject: [PATCH 12/38] =?UTF-8?q?[PC-000]=20feat:=20common:domain=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EA=B3=B5=ED=86=B5=20=EC=9D=91=EB=8B=B5=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 --- .../java/org/yapp/util/CommonResponse.java | 60 +++++++++++++++++++ .../main/java/org/yapp/util/PageResponse.java | 18 ++++++ 2 files changed, 78 insertions(+) create mode 100644 common/format/src/main/java/org/yapp/util/CommonResponse.java create mode 100644 common/format/src/main/java/org/yapp/util/PageResponse.java diff --git a/common/format/src/main/java/org/yapp/util/CommonResponse.java b/common/format/src/main/java/org/yapp/util/CommonResponse.java new file mode 100644 index 0000000..3c29533 --- /dev/null +++ b/common/format/src/main/java/org/yapp/util/CommonResponse.java @@ -0,0 +1,60 @@ +package org.yapp.util; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; + +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class CommonResponse { + + private static final String SUCCESS_STATUS = "success"; + private static final String FAIL_STATUS = "fail"; + private static final String ERROR_STATUS = "error"; + + private String status; + private String message; + private T data; + + private CommonResponse(String status, T data, String message) { + this.status = status; + this.data = data; + this.message = message; + } + + public static CommonResponse createError(String message) { + return new CommonResponse<>(ERROR_STATUS, null, message); + } + + public static CommonResponse createFail(BindingResult bindingResult) { + Map errors = new HashMap<>(); + + List allErrors = bindingResult.getAllErrors(); + for (ObjectError error : allErrors) { + if (error instanceof FieldError) { + errors.put(((FieldError) error).getField(), error.getDefaultMessage()); + } else { + errors.put(error.getObjectName(), error.getDefaultMessage()); + } + } + return new CommonResponse<>(FAIL_STATUS, errors, null); + } + + public static CommonResponse createSuccess(T data) { + return new CommonResponse<>(SUCCESS_STATUS, data, "요청이 성공적으로 처리되었습니다."); + } + + public static CommonResponse createSuccessWithNoContent() { + return new CommonResponse<>(SUCCESS_STATUS, null, null); + } + + public static CommonResponse createSuccessWithNoContent(String message) { + return new CommonResponse<>(SUCCESS_STATUS, null, message); + } +} \ No newline at end of file diff --git a/common/format/src/main/java/org/yapp/util/PageResponse.java b/common/format/src/main/java/org/yapp/util/PageResponse.java new file mode 100644 index 0000000..b3d51d3 --- /dev/null +++ b/common/format/src/main/java/org/yapp/util/PageResponse.java @@ -0,0 +1,18 @@ +package org.yapp.util; + +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class PageResponse { + + private List content; + private int currentPage; + private int pageSize; + private int totalPages; + private long totalElements; + private boolean isFirstPage; + private boolean isLastPage; +} \ No newline at end of file From dd2cb6e2e7d3ae0dac944378d0782223e6a32f47 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 16:15:08 +0900 Subject: [PATCH 13/38] =?UTF-8?q?[PC-380]=20feat:=20admin=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=8B=9C=ED=81=90=EB=A6=AC=ED=8B=B0=20=EC=84=A4?= =?UTF-8?q?=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 --- .../java/org/yapp/config/SecurityConfig.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 admin/src/main/java/org/yapp/config/SecurityConfig.java diff --git a/admin/src/main/java/org/yapp/config/SecurityConfig.java b/admin/src/main/java/org/yapp/config/SecurityConfig.java new file mode 100644 index 0000000..2f50146 --- /dev/null +++ b/admin/src/main/java/org/yapp/config/SecurityConfig.java @@ -0,0 +1,52 @@ +package org.yapp.config; + +import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; + +import java.util.Collections; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.util.matcher.RequestMatcher; +import org.springframework.security.web.util.matcher.RequestMatchers; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.CorsConfigurationSource; + +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class SecurityConfig { + + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + return http.csrf(AbstractHttpConfigurer::disable) + .cors(corsConfigurer -> corsConfigurer.configurationSource(corsConfigurationSource())) + .httpBasic(AbstractHttpConfigurer::disable) + .sessionManagement(configurer -> configurer.sessionCreationPolicy( + SessionCreationPolicy.STATELESS)) + .authorizeHttpRequests(registry -> registry + .requestMatchers(getMatcherForAnyone()) + .permitAll() + .anyRequest() + .hasAnyRole("ADMIN")) + .build(); + } + + private CorsConfigurationSource corsConfigurationSource() { + return request -> { + CorsConfiguration config = new CorsConfiguration(); + config.setAllowedHeaders(Collections.singletonList("*")); + config.setAllowedMethods(Collections.singletonList("*")); + config.setAllowedOriginPatterns(Collections.singletonList("*")); + return config; + }; + } + + private RequestMatcher getMatcherForAnyone() { + return RequestMatchers.anyOf(antMatcher("/admin/v1/login/**")); + } +} \ No newline at end of file From 143c1619e55a2257282057002b1a604096f36a5a Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 16:15:29 +0900 Subject: [PATCH 14/38] =?UTF-8?q?[PC-380]=20chore:=20=EB=8D=94=EB=AF=B8=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=8A=A4=ED=81=AC=EB=A6=BD?= =?UTF-8?q?=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 --- api/src/main/resources/init.sql | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/api/src/main/resources/init.sql b/api/src/main/resources/init.sql index 61cf694..e7e9fb3 100644 --- a/api/src/main/resources/init.sql +++ b/api/src/main/resources/init.sql @@ -1,24 +1,23 @@ -- ProfileBasic 더미 데이터 삽입 -INSERT INTO profile (profile_id, nickname, birthdate, height, job, location, smoking_status, +INSERT INTO profile (nickname, birthdate, height, job, location, smoking_status, religion, sns_activity_level, phone_number, - image_url, contacts) -VALUES (1, 'JohnDoe', '1990-01-01', 180, 'Engineer', 'Seoul', 'Non-smoker', 'None', 'Medium', + image_url, contacts, profile_status) +VALUES ('JohnDoe', '1990-01-01', 180, 'Engineer', 'Seoul', 'Non-smoker', 'None', 'Medium', '010-1234-5678', 'https://example.com/johndoe.jpg', '{ "email": "nomad8@naver.com" }'); --- ProfileBio 더미 데이터 삽입 -UPDATE profile -SET introduction = 'Hello, I am John.', - goal = 'Achieve success.', - interest = 'Coding' -WHERE profile_id = 1; -- User 더미 데이터 삽입 -INSERT INTO user_table (user_id, oauth_id, name, profile_id, role) -VALUES (1, 'oauth123', 'John Doe', 1, 'USER'); +INSERT INTO user_table (oauth_id, name, phone, role, profile_id, created_at, updated_at) +VALUES ('oauth12345', 'Alice', '010-1234-5678', 'ADMIN', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('oauth67890', 'Bob', '010-5678-1234', 'USER', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('oauth13579', 'Charlie', '010-1111-2222', 'USER', NULL, CURRENT_TIMESTAMP, + CURRENT_TIMESTAMP), + ('oauth24680', 'David', '010-3333-4444', 'USER', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), + ('oauth11223', 'Eve', '010-5555-6666', 'USER', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); -- ValueItem 더미 데이터 삽입 INSERT INTO value_pick (value_pick_id, category, question, answers, is_active) From 462c554c1a6022c043009b59a2771d4d61ec7fc8 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 16:34:41 +0900 Subject: [PATCH 15/38] =?UTF-8?q?[PC-380]=20feat:=20admin=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EC=82=AC=EC=9A=A9=EC=9E=90=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/org/yapp/AdminApplication.java | 12 ++++ .../dao/ProfileRejectHistoryRepository.java | 12 ++++ .../yapp/user/application/UserService.java | 64 +++++++++++++++++++ .../org/yapp/user/dao/UserRepository.java | 12 ++++ .../user/presentation/UserController.java | 31 +++++++++ .../UserProfileValidationResponse.java | 33 ++++++++++ .../org/yapp/error/dto/UserErrorCode.java | 16 +++++ 7 files changed, 180 insertions(+) create mode 100644 admin/src/main/java/org/yapp/AdminApplication.java create mode 100644 admin/src/main/java/org/yapp/profile/dao/ProfileRejectHistoryRepository.java create mode 100644 admin/src/main/java/org/yapp/user/application/UserService.java create mode 100644 admin/src/main/java/org/yapp/user/dao/UserRepository.java create mode 100644 admin/src/main/java/org/yapp/user/presentation/UserController.java create mode 100644 admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java create mode 100644 common/exception/src/main/java/org/yapp/error/dto/UserErrorCode.java diff --git a/admin/src/main/java/org/yapp/AdminApplication.java b/admin/src/main/java/org/yapp/AdminApplication.java new file mode 100644 index 0000000..52664ae --- /dev/null +++ b/admin/src/main/java/org/yapp/AdminApplication.java @@ -0,0 +1,12 @@ +package org.yapp; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AdminApplication { + + public static void main(String[] args) { + SpringApplication.run(AdminApplication.class, args); + } +} \ No newline at end of file diff --git a/admin/src/main/java/org/yapp/profile/dao/ProfileRejectHistoryRepository.java b/admin/src/main/java/org/yapp/profile/dao/ProfileRejectHistoryRepository.java new file mode 100644 index 0000000..9c9d8c5 --- /dev/null +++ b/admin/src/main/java/org/yapp/profile/dao/ProfileRejectHistoryRepository.java @@ -0,0 +1,12 @@ +package org.yapp.profile.dao; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.yapp.domain.profile.ProfileRejectHistory; + +@Repository +public interface ProfileRejectHistoryRepository extends JpaRepository { + + Optional findTopByUserIdOrderByCreatedAtDesc(Long userId); +} diff --git a/admin/src/main/java/org/yapp/user/application/UserService.java b/admin/src/main/java/org/yapp/user/application/UserService.java new file mode 100644 index 0000000..2681320 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/application/UserService.java @@ -0,0 +1,64 @@ +package org.yapp.user.application; + +import java.util.List; +import java.util.Optional; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.yapp.domain.profile.ProfileRejectHistory; +import org.yapp.domain.user.User; +import org.yapp.error.dto.UserErrorCode; +import org.yapp.error.exception.ApplicationException; +import org.yapp.profile.dao.ProfileRejectHistoryRepository; +import org.yapp.user.dao.UserRepository; +import org.yapp.user.presentation.response.UserProfileValidationResponse; +import org.yapp.util.PageResponse; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final UserRepository userRepository; + private final ProfileRejectHistoryRepository profileRejectHistoryRepository; + + public User getUserById(Long userId) { + return userRepository.findById(userId) + .orElseThrow(() -> new ApplicationException(UserErrorCode.NOTFOUND_USER)); + } + + public PageResponse getUserProfilesWithPagination(int page, + int size) { + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + + Page userPage = userRepository.findAll(pageable); + + List content = userPage.getContent().stream() + .map(user -> { + Optional optionalProfileRejectHistory = + profileRejectHistoryRepository.findTopByUserIdOrderByCreatedAtDesc( + user.getId()); + + boolean reasonImage = optionalProfileRejectHistory.map( + ProfileRejectHistory::isReasonImage).orElse(false); + boolean reasonDescription = optionalProfileRejectHistory.map( + ProfileRejectHistory::isReasonDescription).orElse(false); + + return UserProfileValidationResponse.from(user, reasonImage, reasonDescription); + }) + .toList(); + + // org.yapp.util.PageResponse 생성 및 반환 + return new PageResponse<>( + content, + userPage.getNumber(), + userPage.getSize(), + userPage.getTotalPages(), + userPage.getTotalElements(), + userPage.isFirst(), + userPage.isLast() + ); + } +} diff --git a/admin/src/main/java/org/yapp/user/dao/UserRepository.java b/admin/src/main/java/org/yapp/user/dao/UserRepository.java new file mode 100644 index 0000000..ce89bd9 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/dao/UserRepository.java @@ -0,0 +1,12 @@ +package org.yapp.user.dao; + +import java.util.Optional; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.yapp.domain.user.User; + +@Repository +public interface UserRepository extends JpaRepository { + + Optional findById(Long userId); +} diff --git a/admin/src/main/java/org/yapp/user/presentation/UserController.java b/admin/src/main/java/org/yapp/user/presentation/UserController.java new file mode 100644 index 0000000..49cd745 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/presentation/UserController.java @@ -0,0 +1,31 @@ +package org.yapp.user.presentation; + +import lombok.RequiredArgsConstructor; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.yapp.user.application.UserService; +import org.yapp.user.presentation.response.UserProfileValidationResponse; +import org.yapp.util.CommonResponse; +import org.yapp.util.PageResponse; + +@RestController() +@RequiredArgsConstructor +@RequestMapping("/admin/v1/users") +public class UserController { + + private final UserService userService; + + @GetMapping("") + public ResponseEntity>> getUsers( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + + PageResponse userProfilesWithPagination = userService.getUserProfilesWithPagination( + page, size); + + return ResponseEntity.ok(CommonResponse.createSuccess(userProfilesWithPagination)); + } +} diff --git a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java new file mode 100644 index 0000000..f062c91 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java @@ -0,0 +1,33 @@ +package org.yapp.user.presentation.response; + +import java.time.LocalDate; +import lombok.Builder; +import org.yapp.domain.profile.Profile; +import org.yapp.domain.user.User; + +@Builder +public record UserProfileValidationResponse(Long userId, String description, + String nickName, + String name, LocalDate birthdate, String phoneNumber, + LocalDate joinDate, + String profileStatus, boolean reasonImage, + boolean reasonDescription) { + + public static UserProfileValidationResponse from(User user, boolean reasonImage, + boolean reasonDescription) { + Profile profile = user.getProfile(); + + return UserProfileValidationResponse.builder() + .userId(user.getId()) + .description(profile != null ? profile.getProfileBasic().getDescription() : null) + .nickName(profile != null ? profile.getProfileBasic().getNickname() : null) + .name(user.getName()) + .birthdate(profile != null ? profile.getProfileBasic().getBirthdate() : null) + .phoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber() : null) + .joinDate(user.getCreatedAt() != null ? user.getCreatedAt().toLocalDate() : null) + .profileStatus(profile != null ? profile.getProfileStatus().getDisplayName() : null) + .reasonImage(reasonImage) + .reasonDescription(reasonDescription) + .build(); + } +} diff --git a/common/exception/src/main/java/org/yapp/error/dto/UserErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/UserErrorCode.java new file mode 100644 index 0000000..e2304b0 --- /dev/null +++ b/common/exception/src/main/java/org/yapp/error/dto/UserErrorCode.java @@ -0,0 +1,16 @@ +package org.yapp.error.dto; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; + +@Getter +@RequiredArgsConstructor +public enum UserErrorCode implements ErrorCode { + INACTIVE_USER(HttpStatus.FORBIDDEN, "User is inactive"), + NOTFOUND_USER(HttpStatus.NOT_FOUND, "User not found"), + ; + + private final HttpStatus httpStatus; + private final String message; +} From 25e84769786b70d8732060afdf89addc1698521c Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 18:02:47 +0900 Subject: [PATCH 16/38] =?UTF-8?q?[PC-381]=20typo:=20nickname=20=ED=94=84?= =?UTF-8?q?=EB=A1=9C=ED=8D=BC=ED=8B=B0=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/response/UserProfileValidationResponse.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java index f062c91..5e3bbae 100644 --- a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java +++ b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java @@ -7,7 +7,7 @@ @Builder public record UserProfileValidationResponse(Long userId, String description, - String nickName, + String nickname, String name, LocalDate birthdate, String phoneNumber, LocalDate joinDate, String profileStatus, boolean reasonImage, @@ -20,7 +20,7 @@ public static UserProfileValidationResponse from(User user, boolean reasonImage, return UserProfileValidationResponse.builder() .userId(user.getId()) .description(profile != null ? profile.getProfileBasic().getDescription() : null) - .nickName(profile != null ? profile.getProfileBasic().getNickname() : null) + .nickname(profile != null ? profile.getProfileBasic().getNickname() : null) .name(user.getName()) .birthdate(profile != null ? profile.getProfileBasic().getBirthdate() : null) .phoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber() : null) From 144424d59a93c89526a912acde1bf7f15c7d38ac Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 18:46:58 +0900 Subject: [PATCH 17/38] =?UTF-8?q?[PC-381]=20fix:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=97=90=EB=9F=AC=20=EC=BD=94=EB=93=9C=20=EB=A9=94?= =?UTF-8?q?=EC=8B=9C=EC=A7=80=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/yapp/error/dto/ProfileErrorCode.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java b/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java index 6ec0c44..4e73c11 100644 --- a/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java +++ b/common/exception/src/main/java/org/yapp/error/dto/ProfileErrorCode.java @@ -7,8 +7,8 @@ @Getter @RequiredArgsConstructor public enum ProfileErrorCode implements ErrorCode { - INACTIVE_PROFILE(HttpStatus.FORBIDDEN, "Profile is inactive"), - NOTFOUND_PROFILE(HttpStatus.NOT_FOUND, "Profile not found"), + INACTIVE_PROFILE(HttpStatus.FORBIDDEN, "비활성화 프로필입니다."), + NOTFOUND_PROFILE(HttpStatus.NOT_FOUND, "존재하지 않는 프로필입니다."), ; private final HttpStatus httpStatus; From 898c387b9de1a14890bdd5719f6f7ba397176cc0 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Sun, 19 Jan 2025 19:02:12 +0900 Subject: [PATCH 18/38] =?UTF-8?q?[PC-381]=20feat:=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=ED=95=84=20=EC=83=81=EC=85=8D=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dao/ProfileValueTalkRepository.java | 18 +++++++++++++ .../yapp/user/application/UserService.java | 25 ++++++++++++++++++- .../user/presentation/UserController.java | 10 ++++++++ .../response/UserProfileDetailResponse.java | 18 +++++++++++++ .../response/UserProfileDetailResponses.java | 16 ++++++++++++ 5 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 admin/src/main/java/org/yapp/profile/dao/ProfileValueTalkRepository.java create mode 100644 admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponse.java create mode 100644 admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponses.java diff --git a/admin/src/main/java/org/yapp/profile/dao/ProfileValueTalkRepository.java b/admin/src/main/java/org/yapp/profile/dao/ProfileValueTalkRepository.java new file mode 100644 index 0000000..6fd4b13 --- /dev/null +++ b/admin/src/main/java/org/yapp/profile/dao/ProfileValueTalkRepository.java @@ -0,0 +1,18 @@ +package org.yapp.profile.dao; + +import io.lettuce.core.dynamic.annotation.Param; +import java.util.List; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import org.yapp.domain.profile.ProfileValueTalk; + +@Repository +public interface ProfileValueTalkRepository extends JpaRepository { + + @Query("SELECT pvt FROM ProfileValueTalk pvt " + + "JOIN FETCH pvt.valueTalk vt " + + "WHERE vt.isActive = true AND pvt.profile.id = :profileId") + List findActiveProfileValueTalksByProfileId( + @Param("profileId") Long profileId); +} \ No newline at end of file diff --git a/admin/src/main/java/org/yapp/user/application/UserService.java b/admin/src/main/java/org/yapp/user/application/UserService.java index 2681320..c206404 100644 --- a/admin/src/main/java/org/yapp/user/application/UserService.java +++ b/admin/src/main/java/org/yapp/user/application/UserService.java @@ -8,12 +8,18 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.yapp.domain.profile.Profile; import org.yapp.domain.profile.ProfileRejectHistory; +import org.yapp.domain.profile.ProfileValueTalk; import org.yapp.domain.user.User; +import org.yapp.error.dto.ProfileErrorCode; import org.yapp.error.dto.UserErrorCode; import org.yapp.error.exception.ApplicationException; import org.yapp.profile.dao.ProfileRejectHistoryRepository; +import org.yapp.profile.dao.ProfileValueTalkRepository; import org.yapp.user.dao.UserRepository; +import org.yapp.user.presentation.response.UserProfileDetailResponses; import org.yapp.user.presentation.response.UserProfileValidationResponse; import org.yapp.util.PageResponse; @@ -23,6 +29,7 @@ public class UserService { private final UserRepository userRepository; private final ProfileRejectHistoryRepository profileRejectHistoryRepository; + private final ProfileValueTalkRepository profileValueTalkRepository; public User getUserById(Long userId) { return userRepository.findById(userId) @@ -50,7 +57,6 @@ public PageResponse getUserProfilesWithPagination }) .toList(); - // org.yapp.util.PageResponse 생성 및 반환 return new PageResponse<>( content, userPage.getNumber(), @@ -61,4 +67,21 @@ public PageResponse getUserProfilesWithPagination userPage.isLast() ); } + + @Transactional(readOnly = true) + public UserProfileDetailResponses getUserProfileDetails(Long userId) { + User user = getUserById(userId); + Profile profile = user.getProfile(); + + if (profile == null) { + throw new ApplicationException(ProfileErrorCode.NOTFOUND_PROFILE); + } + + List activeProfileValueTalks = profileValueTalkRepository.findActiveProfileValueTalksByProfileId( + profile.getId()); + + return UserProfileDetailResponses.from(profile.getProfileBasic().getNickname(), + profile.getProfileBasic().getImageUrl(), + activeProfileValueTalks); + } } diff --git a/admin/src/main/java/org/yapp/user/presentation/UserController.java b/admin/src/main/java/org/yapp/user/presentation/UserController.java index 49cd745..ab6fcd7 100644 --- a/admin/src/main/java/org/yapp/user/presentation/UserController.java +++ b/admin/src/main/java/org/yapp/user/presentation/UserController.java @@ -3,10 +3,12 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.yapp.user.application.UserService; +import org.yapp.user.presentation.response.UserProfileDetailResponses; import org.yapp.user.presentation.response.UserProfileValidationResponse; import org.yapp.util.CommonResponse; import org.yapp.util.PageResponse; @@ -28,4 +30,12 @@ public ResponseEntity return ResponseEntity.ok(CommonResponse.createSuccess(userProfilesWithPagination)); } + + @GetMapping("/{userId}") + public ResponseEntity> getUserProfile( + @PathVariable long userId) { + + UserProfileDetailResponses userProfileDetails = userService.getUserProfileDetails(userId); + return ResponseEntity.ok(CommonResponse.createSuccess(userProfileDetails)); + } } diff --git a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponse.java b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponse.java new file mode 100644 index 0000000..dfe5a58 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponse.java @@ -0,0 +1,18 @@ +package org.yapp.user.presentation.response; + +import org.yapp.domain.profile.ProfileValueTalk; + +public record UserProfileDetailResponse( + String category, + String title, + String answer +) { + + public UserProfileDetailResponse(ProfileValueTalk profileValueTalk) { + this( + profileValueTalk.getValueTalk().getTitle(), + profileValueTalk.getValueTalk().getCategory(), + profileValueTalk.getAnswer() + ); + } +} diff --git a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponses.java b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponses.java new file mode 100644 index 0000000..6611053 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileDetailResponses.java @@ -0,0 +1,16 @@ +package org.yapp.user.presentation.response; + +import java.util.List; +import org.yapp.domain.profile.ProfileValueTalk; + +public record UserProfileDetailResponses(String nickname, String imageUrl, + List responses) { + + public static UserProfileDetailResponses from(String nickname, String imageUrl, + List profileValueTalks) { + List profileValueTalkResponses = profileValueTalks.stream() + .map(UserProfileDetailResponse::new).toList(); + + return new UserProfileDetailResponses(nickname, imageUrl, profileValueTalkResponses); + } +} From abefcb7fc21b8e51a9ccbc7523529a00b78c6d19 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Mon, 20 Jan 2025 21:27:55 +0900 Subject: [PATCH 19/38] =?UTF-8?q?[PC-384]=20feat:=20=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/yapp/domain/report/Report.java | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 common/domain/src/main/java/org/yapp/domain/report/Report.java diff --git a/common/domain/src/main/java/org/yapp/domain/report/Report.java b/common/domain/src/main/java/org/yapp/domain/report/Report.java new file mode 100644 index 0000000..a5c27ef --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/report/Report.java @@ -0,0 +1,37 @@ +package org.yapp.domain.report; + +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.OneToOne; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.user.User; + +@Entity +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class Report extends BaseEntity { + + @Id + @Column(name = "report_id") + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @OneToOne + @JoinColumn(name = "reporter_user_id", nullable = false) + private User reporter; + + @OneToOne + @JoinColumn(name = "reported_user_id", nullable = false) + private User reportedUser; + + @Column(length = 500) + private String reason; +} From 596bd68f1047728ce63c8dc2cab41cba0fdcb8c1 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Mon, 20 Jan 2025 23:09:00 +0900 Subject: [PATCH 20/38] =?UTF-8?q?[PC-384]=20feat:=20ManyToOne=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=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 --- .../domain/src/main/java/org/yapp/domain/report/Report.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/domain/src/main/java/org/yapp/domain/report/Report.java b/common/domain/src/main/java/org/yapp/domain/report/Report.java index a5c27ef..61c9c87 100644 --- a/common/domain/src/main/java/org/yapp/domain/report/Report.java +++ b/common/domain/src/main/java/org/yapp/domain/report/Report.java @@ -6,7 +6,7 @@ import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; -import jakarta.persistence.OneToOne; +import jakarta.persistence.ManyToOne; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.NoArgsConstructor; @@ -24,11 +24,11 @@ public class Report extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne + @ManyToOne @JoinColumn(name = "reporter_user_id", nullable = false) private User reporter; - @OneToOne + @ManyToOne @JoinColumn(name = "reported_user_id", nullable = false) private User reportedUser; From 1a84a2fd77ffe53575ca0eb039d5d75d97526ded Mon Sep 17 00:00:00 2001 From: LujaeC Date: Mon, 20 Jan 2025 23:09:25 +0900 Subject: [PATCH 21/38] =?UTF-8?q?[PC-384]=20feat:=20=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=EB=A6=AC=EC=8A=A4=ED=8A=B8=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/application/ReportService.java | 46 +++++++++++++++++++ .../dto/ReportedUserWithReasonDto.java | 19 ++++++++ .../org/yapp/report/dao/ReportRepository.java | 25 ++++++++++ .../report/presentation/ReportController.java | 31 +++++++++++++ .../response/ReportUserResponse.java | 8 ++++ 5 files changed, 129 insertions(+) create mode 100644 admin/src/main/java/org/yapp/report/application/ReportService.java create mode 100644 admin/src/main/java/org/yapp/report/application/dto/ReportedUserWithReasonDto.java create mode 100644 admin/src/main/java/org/yapp/report/dao/ReportRepository.java create mode 100644 admin/src/main/java/org/yapp/report/presentation/ReportController.java create mode 100644 admin/src/main/java/org/yapp/report/presentation/response/ReportUserResponse.java diff --git a/admin/src/main/java/org/yapp/report/application/ReportService.java b/admin/src/main/java/org/yapp/report/application/ReportService.java new file mode 100644 index 0000000..c213b93 --- /dev/null +++ b/admin/src/main/java/org/yapp/report/application/ReportService.java @@ -0,0 +1,46 @@ +package org.yapp.report.application; + +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.yapp.report.application.dto.ReportedUserWithReasonDto; +import org.yapp.report.dao.ReportRepository; +import org.yapp.report.presentation.response.ReportUserResponse; +import org.yapp.util.PageResponse; + +@Service +@RequiredArgsConstructor +public class ReportService { + + private final ReportRepository reportRepository; + + public PageResponse getReportedUsersWithCount(int page, int size) { + Pageable pageable = PageRequest.of(page, size); + + Page reportedUserPage = reportRepository.findReportedUsersWithLatestReason( + pageable); + + Page reportUserResponsePage = reportedUserPage.map(dto -> + new ReportUserResponse( + dto.getUser().getId(), + dto.getUser().getProfile().getProfileBasic().getNickname(), + dto.getUser().getName(), + dto.getUser().getProfile().getProfileBasic().getBirthdate(), + dto.getReportCount(), + dto.getLatestReason() + ) + ); + + return new PageResponse<>( + reportUserResponsePage.getContent(), + reportUserResponsePage.getNumber(), + reportUserResponsePage.getSize(), + reportUserResponsePage.getTotalPages(), + reportUserResponsePage.getTotalElements(), + reportUserResponsePage.isFirst(), + reportUserResponsePage.isLast() + ); + } +} diff --git a/admin/src/main/java/org/yapp/report/application/dto/ReportedUserWithReasonDto.java b/admin/src/main/java/org/yapp/report/application/dto/ReportedUserWithReasonDto.java new file mode 100644 index 0000000..8a3fc55 --- /dev/null +++ b/admin/src/main/java/org/yapp/report/application/dto/ReportedUserWithReasonDto.java @@ -0,0 +1,19 @@ +package org.yapp.report.application.dto; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; +import org.yapp.domain.user.User; + +@Getter +@NoArgsConstructor +@AllArgsConstructor +@Setter +public class ReportedUserWithReasonDto { + + private User user; + private Long reportCount; + private String latestReason; +} \ No newline at end of file diff --git a/admin/src/main/java/org/yapp/report/dao/ReportRepository.java b/admin/src/main/java/org/yapp/report/dao/ReportRepository.java new file mode 100644 index 0000000..5af21d1 --- /dev/null +++ b/admin/src/main/java/org/yapp/report/dao/ReportRepository.java @@ -0,0 +1,25 @@ +package org.yapp.report.dao; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.stereotype.Repository; +import org.yapp.domain.report.Report; +import org.yapp.report.application.dto.ReportedUserWithReasonDto; + +@Repository +public interface ReportRepository extends JpaRepository { + + + @Query("SELECT new org.yapp.report.application.dto.ReportedUserWithReasonDto(" + + "r.reportedUser, COUNT(r), " + + "(SELECT r2.reason FROM Report r2 " + + " WHERE r2.reportedUser = r.reportedUser " + + " ORDER BY r2.createdAt DESC LIMIT 1)) " + + "FROM Report r " + + "GROUP BY r.reportedUser " + + "HAVING COUNT(r) >= 1 " + + "ORDER BY MAX(r.createdAt) DESC") + Page findReportedUsersWithLatestReason(Pageable pageable); +} diff --git a/admin/src/main/java/org/yapp/report/presentation/ReportController.java b/admin/src/main/java/org/yapp/report/presentation/ReportController.java new file mode 100644 index 0000000..dca2610 --- /dev/null +++ b/admin/src/main/java/org/yapp/report/presentation/ReportController.java @@ -0,0 +1,31 @@ +package org.yapp.report.presentation; + +import lombok.RequiredArgsConstructor; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.yapp.report.application.ReportService; +import org.yapp.report.presentation.response.ReportUserResponse; +import org.yapp.util.CommonResponse; +import org.yapp.util.PageResponse; + +@RestController() +@RequiredArgsConstructor +@RequestMapping("/admin/v1/reports") +public class ReportController { + + private final ReportService reportService; + + @GetMapping("") + public ResponseEntity>> getUsers( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + + PageResponse reportedUsersWithCount = reportService.getReportedUsersWithCount( + page, size); + + return ResponseEntity.ok(CommonResponse.createSuccess(reportedUsersWithCount)); + } +} diff --git a/admin/src/main/java/org/yapp/report/presentation/response/ReportUserResponse.java b/admin/src/main/java/org/yapp/report/presentation/response/ReportUserResponse.java new file mode 100644 index 0000000..1ffebf6 --- /dev/null +++ b/admin/src/main/java/org/yapp/report/presentation/response/ReportUserResponse.java @@ -0,0 +1,8 @@ +package org.yapp.report.presentation.response; + +import java.time.LocalDate; + +public record ReportUserResponse(Long userId, String nickName, String name, LocalDate birthdate, + Long totalReportedCnt, String latestReportedReason) { + +} From 1ed90307467bec681f96fffd96a55fe652aeaf63 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Mon, 20 Jan 2025 23:09:42 +0900 Subject: [PATCH 22/38] =?UTF-8?q?[PC-384]=20fix:=20=EB=8D=94=EB=AF=B8=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=88=98=EC=A0=95=20(=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=EC=9E=90,=20=ED=94=84=EB=A1=9C=ED=95=84=2010=EA=B0=9C?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/src/main/resources/init.sql | 93 ++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 20 deletions(-) diff --git a/api/src/main/resources/init.sql b/api/src/main/resources/init.sql index e7e9fb3..9f360cb 100644 --- a/api/src/main/resources/init.sql +++ b/api/src/main/resources/init.sql @@ -1,23 +1,76 @@ -- ProfileBasic 더미 데이터 삽입 -INSERT INTO profile (nickname, birthdate, height, job, location, smoking_status, - religion, - sns_activity_level, phone_number, - image_url, contacts, profile_status) -VALUES ('JohnDoe', '1990-01-01', 180, 'Engineer', 'Seoul', 'Non-smoker', 'None', 'Medium', - '010-1234-5678', - 'https://example.com/johndoe.jpg', '{ - "email": "nomad8@naver.com" - }'); - - --- User 더미 데이터 삽입 -INSERT INTO user_table (oauth_id, name, phone, role, profile_id, created_at, updated_at) -VALUES ('oauth12345', 'Alice', '010-1234-5678', 'ADMIN', 1, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), - ('oauth67890', 'Bob', '010-5678-1234', 'USER', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), - ('oauth13579', 'Charlie', '010-1111-2222', 'USER', NULL, CURRENT_TIMESTAMP, - CURRENT_TIMESTAMP), - ('oauth24680', 'David', '010-3333-4444', 'USER', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP), - ('oauth11223', 'Eve', '010-5555-6666', 'USER', NULL, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP); +INSERT INTO profile (profile_id, profile_status, nickname, description, birthdate, height, job, + location, smoking_status, weight, sns_activity_level, contacts, image_url, + created_at, updated_at) +VALUES (1, 'APPROVED', 'johndoe', '소프트웨어 개발자', '1990-05-10', 180, '엔지니어', '서울', '비흡연자', 75, '활동적', + '{ + "email": "john.doe@example.com" + }', 'https://example.com/john.jpg', NOW(), NOW()), + (2, 'APPROVED', 'janesmith', '마케팅 매니저', '1992-08-15', 165, '마케터', '인천', '비흡연자', 55, '보통', '{ + "email": "jane.smith@example.com" + }', 'https://example.com/jane.jpg', NOW(), NOW()), + (3, 'APPROVED', 'robbrown', '그래픽 디자이너', '1988-03-22', 175, '디자이너', '부산', '흡연자', 70, '낮음', '{ + "email": "robert.brown@example.com" + }', 'https://example.com/robert.jpg', NOW(), NOW()), + (4, 'APPROVED', 'emilydavis', 'HR 전문가', '1995-09-10', 170, 'HR', '대구', '비흡연자', 60, '활동적', '{ + "email": "emily.davis@example.com" + }', 'https://example.com/emily.jpg', NOW(), NOW()), + (5, 'APPROVED', 'mikejohnson', '데이터 과학자', '1993-12-01', 185, '과학자', '서울', '비흡연자', 80, + '매우 활동적', '{ + "email": "michael.johnson@example.com" + }', 'https://example.com/mike.jpg', NOW(), NOW()), + (6, 'APPROVED', 'sarahwilson', '학교 교사', '1985-04-17', 160, '교사', '광주', '비흡연자', 50, '보통', '{ + "email": "sarah.wilson@example.com" + }', 'https://example.com/sarah.jpg', NOW(), NOW()), + (7, 'APPROVED', 'davidmartinez', '프로젝트 매니저', '1991-11-11', 172, '매니저', '수원', '비흡연자', 68, + '활동적', '{ + "email": "david.martinez@example.com" + }', 'https://example.com/david.jpg', NOW(), NOW()), + (8, 'APPROVED', 'laurawhite', '비즈니스 분석가', '1987-06-25', 167, '분석가', '대전', '비흡연자', 58, '낮음', + '{ + "email": "laura.white@example.com" + }', 'https://example.com/laura.jpg', NOW(), NOW()), + (9, 'APPROVED', 'jamesanderson', '기업가', '1990-01-19', 178, '기업가', '서울', '흡연자', 72, '매우 활동적', + '{ + "email": "james.anderson@example.com" + }', 'https://example.com/james.jpg', NOW(), NOW()), + (10, 'APPROVED', 'oliviataylor', '제품 디자이너', '1994-07-30', 162, '디자이너', '울산', '비흡연자', 54, + '보통', '{ + "email": "olivia.taylor@example.com" + }', 'https://example.com/olivia.jpg', NOW(), NOW()); + + +INSERT INTO user_table (user_id, oauth_id, name, phone, role, profile_id, created_at, updated_at) +VALUES (1, 'oauth_1', '홍길동', '010-1234-5678', 'USER', 1, NOW(), NOW()), + (2, 'oauth_2', '김철수', '010-2345-6789', 'USER', 2, NOW(), NOW()), + (3, 'oauth_3', '이영희', '010-3456-7890', 'USER', 3, NOW(), NOW()), + (4, 'oauth_4', '박민수', '010-4567-8901', 'USER', 4, NOW(), NOW()), + (5, 'oauth_5', '최지우', '010-5678-9012', 'USER', 5, NOW(), NOW()), + (6, 'oauth_6', '강하늘', '010-6789-0123', 'USER', 6, NOW(), NOW()), + (7, 'oauth_7', '오세훈', '010-7890-1234', 'USER', 7, NOW(), NOW()), + (8, 'oauth_8', '장미란', '010-8901-2345', 'USER', 8, NOW(), NOW()), + (9, 'oauth_9', '정다은', '010-9012-3456', 'USER', 9, NOW(), NOW()), + (10, 'oauth_10', '김유진', '010-0123-4567', 'USER', 10, NOW(), NOW()); + +INSERT INTO report (report_id, reporter_user_id, reported_user_id, reason, created_at, updated_at) +VALUES (1, 1, 2, '부적절한 언어 사용', NOW(), NOW()), + (2, 3, 4, '스팸 메시지 전송', NOW(), NOW()), + (3, 5, 6, '허위 정보 제공', NOW(), NOW()), + (4, 7, 8, '욕설 및 비방', NOW(), NOW()), + (5, 9, 10, '기타 사유', NOW(), NOW()), + (6, 2, 1, '사기 의심', NOW(), NOW()), + (7, 4, 3, '허위 정보 제공', NOW(), NOW()), + (8, 6, 5, '욕설 및 비방', NOW(), NOW()), + (9, 8, 7, '부적절한 언어 사용', NOW(), NOW()), + (10, 10, 9, '스팸 메시지 전송', NOW(), NOW()); + +INSERT INTO report (report_id, reporter_user_id, reported_user_id, reason, created_at, updated_at) +VALUES (11, 3, 2, '부적절한 언어 사용 2222', NOW(), NOW()); + + +INSERT INTO report (report_id, reporter_user_id, reported_user_id, reason, created_at, updated_at) +VALUES (12, 1, 2, '부적절한 언어 사용 3333', NOW(), NOW()); + -- ValueItem 더미 데이터 삽입 INSERT INTO value_pick (value_pick_id, category, question, answers, is_active) @@ -39,7 +92,7 @@ VALUES ('꿈과 목표', '어떤 일을 하며 무엇을 목표로 살아가나 INSERT INTO profile_value_pick (profile_value_pick_id, profile_id, value_pick_id, selected_answer) VALUES (1, 1, 1, 2), - (2, 1, 2, 3); + (2, 1, 2, 1); INSERT INTO profile_value_talk (profile_value_talk_id, profile_id, value_talk_id, answer) VALUES (1, 1, 1, '문장입니다 1'), From bbdb68bab4fd4c5fade88d706fca8b563b6ce430 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Tue, 21 Jan 2025 00:24:28 +0900 Subject: [PATCH 23/38] =?UTF-8?q?[PC-384]=20feat:=20=EC=8B=A0=EA=B3=A0=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../report/application/ReportService.java | 32 +++++++++++++++++++ .../org/yapp/report/dao/ReportRepository.java | 8 +++++ .../report/presentation/ReportController.java | 15 +++++++++ .../response/ReportDetailResponse.java | 7 ++++ .../java/org/yapp/domain/report/Report.java | 2 ++ 5 files changed, 64 insertions(+) create mode 100644 admin/src/main/java/org/yapp/report/presentation/response/ReportDetailResponse.java diff --git a/admin/src/main/java/org/yapp/report/application/ReportService.java b/admin/src/main/java/org/yapp/report/application/ReportService.java index c213b93..3568fce 100644 --- a/admin/src/main/java/org/yapp/report/application/ReportService.java +++ b/admin/src/main/java/org/yapp/report/application/ReportService.java @@ -1,12 +1,16 @@ package org.yapp.report.application; +import java.util.ArrayList; +import java.util.List; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; +import org.yapp.domain.report.Report; import org.yapp.report.application.dto.ReportedUserWithReasonDto; import org.yapp.report.dao.ReportRepository; +import org.yapp.report.presentation.response.ReportDetailResponse; import org.yapp.report.presentation.response.ReportUserResponse; import org.yapp.util.PageResponse; @@ -43,4 +47,32 @@ public PageResponse getReportedUsersWithCount(int page, int reportUserResponsePage.isLast() ); } + + public PageResponse getReportsByReportedUserId(Long reportedUserId, + int page, int size) { + Pageable pageable = PageRequest.of(page, size); + + int order = 1; + Page reportPage = reportRepository.findAllByReportedUserIdOrderByCreatedAt( + reportedUserId, pageable); + List content = new ArrayList<>(); + + for (Report report : reportPage.getContent()) { + content.add(new ReportDetailResponse( + order++, + report.getReason(), + report.getCreatedAt().toLocalDate() + )); + } + + return new PageResponse<>( + content, + reportPage.getNumber(), + reportPage.getSize(), + reportPage.getTotalPages(), + reportPage.getTotalElements(), + reportPage.isFirst(), + reportPage.isLast() + ); + } } diff --git a/admin/src/main/java/org/yapp/report/dao/ReportRepository.java b/admin/src/main/java/org/yapp/report/dao/ReportRepository.java index 5af21d1..57c54d3 100644 --- a/admin/src/main/java/org/yapp/report/dao/ReportRepository.java +++ b/admin/src/main/java/org/yapp/report/dao/ReportRepository.java @@ -4,6 +4,7 @@ import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.springframework.stereotype.Repository; import org.yapp.domain.report.Report; import org.yapp.report.application.dto.ReportedUserWithReasonDto; @@ -22,4 +23,11 @@ public interface ReportRepository extends JpaRepository { "HAVING COUNT(r) >= 1 " + "ORDER BY MAX(r.createdAt) DESC") Page findReportedUsersWithLatestReason(Pageable pageable); + + + @Query("SELECT r FROM Report r " + + "WHERE r.reportedUser.id = :reportedUserId " + + "ORDER BY r.createdAt ASC") + Page findAllByReportedUserIdOrderByCreatedAt( + @Param("reportedUserId") Long reportedUserId, Pageable pageable); } diff --git a/admin/src/main/java/org/yapp/report/presentation/ReportController.java b/admin/src/main/java/org/yapp/report/presentation/ReportController.java index dca2610..e493b94 100644 --- a/admin/src/main/java/org/yapp/report/presentation/ReportController.java +++ b/admin/src/main/java/org/yapp/report/presentation/ReportController.java @@ -3,10 +3,12 @@ import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.yapp.report.application.ReportService; +import org.yapp.report.presentation.response.ReportDetailResponse; import org.yapp.report.presentation.response.ReportUserResponse; import org.yapp.util.CommonResponse; import org.yapp.util.PageResponse; @@ -28,4 +30,17 @@ public ResponseEntity>> getUsers return ResponseEntity.ok(CommonResponse.createSuccess(reportedUsersWithCount)); } + + @GetMapping("/users/{userId}") + public ResponseEntity>> getReportDetails( + @PathVariable Long userId, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "5") int size) { + + PageResponse reportDetailResponses = reportService.getReportsByReportedUserId( + userId, + page, size); + + return ResponseEntity.ok(CommonResponse.createSuccess(reportDetailResponses)); + } } diff --git a/admin/src/main/java/org/yapp/report/presentation/response/ReportDetailResponse.java b/admin/src/main/java/org/yapp/report/presentation/response/ReportDetailResponse.java new file mode 100644 index 0000000..5b3bf91 --- /dev/null +++ b/admin/src/main/java/org/yapp/report/presentation/response/ReportDetailResponse.java @@ -0,0 +1,7 @@ +package org.yapp.report.presentation.response; + +import java.time.LocalDate; + +public record ReportDetailResponse(Integer cnt, String reason, LocalDate reportedDate) { + +} diff --git a/common/domain/src/main/java/org/yapp/domain/report/Report.java b/common/domain/src/main/java/org/yapp/domain/report/Report.java index 61c9c87..fc8dd10 100644 --- a/common/domain/src/main/java/org/yapp/domain/report/Report.java +++ b/common/domain/src/main/java/org/yapp/domain/report/Report.java @@ -9,6 +9,7 @@ import jakarta.persistence.ManyToOne; import lombok.AllArgsConstructor; import lombok.Builder; +import lombok.Getter; import lombok.NoArgsConstructor; import org.yapp.domain.BaseEntity; import org.yapp.domain.user.User; @@ -17,6 +18,7 @@ @NoArgsConstructor @AllArgsConstructor @Builder +@Getter public class Report extends BaseEntity { @Id From 0fc3306fbdd58610dc30f156589a5f0f51ca424c Mon Sep 17 00:00:00 2001 From: LujaeC Date: Tue, 21 Jan 2025 00:40:15 +0900 Subject: [PATCH 24/38] =?UTF-8?q?[PC-383]=20fix:=20=EC=97=B0=EB=9D=BD?= =?UTF-8?q?=EC=B2=98=20=EA=B8=B0=EB=B0=98=20=EC=B0=A8=EB=8B=A8=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95=20(Block=20->=20BlockCo?= =?UTF-8?q?ntact)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/BlockContactService.java | 49 +++++++++++++++++ .../block/application/BlockService.java | 49 ----------------- .../dto/BlockContactCreateDto.java | 13 +++++ .../block/application/dto/BlockCreateDto.java | 12 ----- ...itory.java => BlockContactRepository.java} | 10 ++-- .../presentation/BlockContactController.java | 52 +++++++++++++++++++ .../block/presentation/BlockController.java | 40 -------------- ...esponse.java => BlockContactResponse.java} | 3 +- .../response/UserBlockContactResponses.java | 20 +++++++ .../dto/response/UserBlockResponses.java | 17 ------ .../block/{Block.java => BlockContact.java} | 2 +- 11 files changed, 142 insertions(+), 125 deletions(-) create mode 100644 api/src/main/java/org/yapp/domain/block/application/BlockContactService.java delete mode 100644 api/src/main/java/org/yapp/domain/block/application/BlockService.java create mode 100644 api/src/main/java/org/yapp/domain/block/application/dto/BlockContactCreateDto.java delete mode 100644 api/src/main/java/org/yapp/domain/block/application/dto/BlockCreateDto.java rename api/src/main/java/org/yapp/domain/block/dao/{BlockRepository.java => BlockContactRepository.java} (50%) create mode 100644 api/src/main/java/org/yapp/domain/block/presentation/BlockContactController.java delete mode 100644 api/src/main/java/org/yapp/domain/block/presentation/BlockController.java rename api/src/main/java/org/yapp/domain/block/presentation/dto/response/{BlockResponse.java => BlockContactResponse.java} (52%) create mode 100644 api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockContactResponses.java delete mode 100644 api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockResponses.java rename common/domain/src/main/java/org/yapp/domain/block/{Block.java => BlockContact.java} (96%) diff --git a/api/src/main/java/org/yapp/domain/block/application/BlockContactService.java b/api/src/main/java/org/yapp/domain/block/application/BlockContactService.java new file mode 100644 index 0000000..48bd1c6 --- /dev/null +++ b/api/src/main/java/org/yapp/domain/block/application/BlockContactService.java @@ -0,0 +1,49 @@ +package org.yapp.domain.block.application; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.yapp.domain.block.BlockContact; +import org.yapp.domain.block.application.dto.BlockContactCreateDto; +import org.yapp.domain.block.dao.BlockContactRepository; +import org.yapp.domain.user.User; + +@Service +@RequiredArgsConstructor +public class BlockContactService { + + private final BlockContactRepository blockContactRepository; + + @Transactional() + public void blockPhoneNumbers(BlockContactCreateDto blockContactCreateDto) { + Long userId = blockContactCreateDto.userId(); + List phoneNumbers = blockContactCreateDto.phoneNumbers(); + List newBlockContacts = new ArrayList<>(); + + Set blockedPhoneNumbers = blockContactRepository.findBlocksByUserId(userId) + .stream() + .map(BlockContact::getPhoneNumber) + .collect(Collectors.toSet()); + + phoneNumbers.stream() + .filter(phoneNumber -> !blockedPhoneNumbers.contains(phoneNumber)) + .forEach(phoneNumber -> { + BlockContact blockContact = BlockContact.builder() + .user(User.builder().id(userId).build()) + .phoneNumber(phoneNumber) + .build(); + newBlockContacts.add(blockContact); + }); + + blockContactRepository.saveAll(newBlockContacts); + } + + @Transactional(readOnly = false) + public List findBlocksByUserId(Long userId) { + return blockContactRepository.findBlocksByUserId(userId); + } +} diff --git a/api/src/main/java/org/yapp/domain/block/application/BlockService.java b/api/src/main/java/org/yapp/domain/block/application/BlockService.java deleted file mode 100644 index deb9b82..0000000 --- a/api/src/main/java/org/yapp/domain/block/application/BlockService.java +++ /dev/null @@ -1,49 +0,0 @@ -package org.yapp.domain.block.application; - -import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; -import org.yapp.domain.block.Block; -import org.yapp.domain.block.application.dto.BlockCreateDto; -import org.yapp.domain.block.dao.BlockRepository; -import org.yapp.domain.user.User; - -import java.util.ArrayList; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@Service -@RequiredArgsConstructor -public class BlockService { - private final BlockRepository blockRepository; - - @Transactional() - public void blockPhoneNumbers(BlockCreateDto blockCreateDto) { - Long userId = blockCreateDto.userId(); - List phoneNumbers = blockCreateDto.phoneNumbers(); - List newBlocks = new ArrayList<>(); - - Set blockedPhoneNumbers = blockRepository.findBlocksByUserId(userId) - .stream() - .map(Block::getPhoneNumber) - .collect(Collectors.toSet()); - - phoneNumbers.stream() - .filter(phoneNumber -> !blockedPhoneNumbers.contains(phoneNumber)) - .forEach(phoneNumber -> { - Block block = Block.builder() - .user(User.builder().id(userId).build()) - .phoneNumber(phoneNumber) - .build(); - newBlocks.add(block); - }); - - blockRepository.saveAll(newBlocks); - } - - @Transactional(readOnly = false) - public List findBlocksByUserId(Long userId) { - return blockRepository.findBlocksByUserId(userId); - } -} diff --git a/api/src/main/java/org/yapp/domain/block/application/dto/BlockContactCreateDto.java b/api/src/main/java/org/yapp/domain/block/application/dto/BlockContactCreateDto.java new file mode 100644 index 0000000..81f8363 --- /dev/null +++ b/api/src/main/java/org/yapp/domain/block/application/dto/BlockContactCreateDto.java @@ -0,0 +1,13 @@ +package org.yapp.domain.block.application.dto; + +import java.util.List; + +public record BlockContactCreateDto(Long userId, List phoneNumbers) { + + public BlockContactCreateDto(Long userId, List phoneNumbers) { + this.userId = userId; + this.phoneNumbers = phoneNumbers.stream() + .map(phone -> phone.replaceAll("-", "")) + .toList(); + } +} diff --git a/api/src/main/java/org/yapp/domain/block/application/dto/BlockCreateDto.java b/api/src/main/java/org/yapp/domain/block/application/dto/BlockCreateDto.java deleted file mode 100644 index f769965..0000000 --- a/api/src/main/java/org/yapp/domain/block/application/dto/BlockCreateDto.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.yapp.domain.block.application.dto; - -import java.util.List; - -public record BlockCreateDto(Long userId, List phoneNumbers) { - public BlockCreateDto(Long userId, List phoneNumbers) { - this.userId = userId; - this.phoneNumbers = phoneNumbers.stream() - .map(phone -> phone.replaceAll("-", "")) - .toList(); - } -} diff --git a/api/src/main/java/org/yapp/domain/block/dao/BlockRepository.java b/api/src/main/java/org/yapp/domain/block/dao/BlockContactRepository.java similarity index 50% rename from api/src/main/java/org/yapp/domain/block/dao/BlockRepository.java rename to api/src/main/java/org/yapp/domain/block/dao/BlockContactRepository.java index 2fe32ad..9f5c9e4 100644 --- a/api/src/main/java/org/yapp/domain/block/dao/BlockRepository.java +++ b/api/src/main/java/org/yapp/domain/block/dao/BlockContactRepository.java @@ -1,12 +1,12 @@ package org.yapp.domain.block.dao; +import java.util.List; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.stereotype.Repository; -import org.yapp.domain.block.Block; - -import java.util.List; +import org.yapp.domain.block.BlockContact; @Repository -public interface BlockRepository extends JpaRepository { - List findBlocksByUserId(Long userId); +public interface BlockContactRepository extends JpaRepository { + + List findBlocksByUserId(Long userId); } diff --git a/api/src/main/java/org/yapp/domain/block/presentation/BlockContactController.java b/api/src/main/java/org/yapp/domain/block/presentation/BlockContactController.java new file mode 100644 index 0000000..acf8e38 --- /dev/null +++ b/api/src/main/java/org/yapp/domain/block/presentation/BlockContactController.java @@ -0,0 +1,52 @@ +package org.yapp.domain.block.presentation; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.GetMapping; +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; +import org.yapp.domain.block.BlockContact; +import org.yapp.domain.block.application.BlockContactService; +import org.yapp.domain.block.application.dto.BlockContactCreateDto; +import org.yapp.domain.block.presentation.dto.request.BlockPhoneNumbersRequest; +import org.yapp.domain.block.presentation.dto.response.UserBlockContactResponses; +import org.yapp.util.CommonResponse; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/blockContacts") +public class BlockContactController { + + private final BlockContactService blockContactService; + + @PostMapping("") + @Operation(summary = "핸드폰 번호 차단", description = "핸드폰 번호 리스트를 전달받고, 전달받은 핸드폰 번호 차단을 수행합니다.", tags = { + "차단"}) + @ApiResponse(responseCode = "200", description = "핸드폰 차단 성공") + public ResponseEntity> blockPhoneNumbers( + @AuthenticationPrincipal Long userId, @RequestBody BlockPhoneNumbersRequest request) { + blockContactService.blockPhoneNumbers( + new BlockContactCreateDto(userId, request.phoneNumbers())); + return ResponseEntity.status(HttpStatus.OK) + .body(CommonResponse.createSuccessWithNoContent("핸드폰 번호 차단 성공")); + } + + @GetMapping("") + @Operation(summary = "핸드폰 번호 차단", description = "핸드폰 번호 리스트를 전달받고, 전달받은 핸드폰 번호 차단을 수행합니다.", tags = { + "차단"}) + @ApiResponse(responseCode = "200", description = "핸드폰 차단 성공") + public ResponseEntity> blockPhoneNumbers( + @AuthenticationPrincipal Long userId) { + List blockContacts = blockContactService.findBlocksByUserId(userId); + return ResponseEntity.status(HttpStatus.OK) + .body(CommonResponse.createSuccess(UserBlockContactResponses.from(userId, + blockContacts))); + } +} diff --git a/api/src/main/java/org/yapp/domain/block/presentation/BlockController.java b/api/src/main/java/org/yapp/domain/block/presentation/BlockController.java deleted file mode 100644 index 8440371..0000000 --- a/api/src/main/java/org/yapp/domain/block/presentation/BlockController.java +++ /dev/null @@ -1,40 +0,0 @@ -package org.yapp.domain.block.presentation; - -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; -import org.springframework.security.core.annotation.AuthenticationPrincipal; -import org.springframework.web.bind.annotation.*; -import org.yapp.domain.block.Block; -import org.yapp.domain.block.application.BlockService; -import org.yapp.domain.block.application.dto.BlockCreateDto; -import org.yapp.domain.block.presentation.dto.request.BlockPhoneNumbersRequest; -import org.yapp.domain.block.presentation.dto.response.UserBlockResponses; -import org.yapp.util.CommonResponse; - -import java.util.List; - -@RestController -@RequiredArgsConstructor -@RequestMapping("/api/blocks") -public class BlockController { - private final BlockService blockService; - - @PostMapping("") - @Operation(summary = "핸드폰 번호 차단", description = "핸드폰 번호 리스트를 전달받고, 전달받은 핸드폰 번호 차단을 수행합니다.", tags = {"차단"}) - @ApiResponse(responseCode = "200", description = "핸드폰 차단 성공") - public ResponseEntity> blockPhoneNumbers(@AuthenticationPrincipal Long userId, @RequestBody BlockPhoneNumbersRequest request) { - blockService.blockPhoneNumbers(new BlockCreateDto(userId, request.phoneNumbers())); - return ResponseEntity.status(HttpStatus.OK).body(CommonResponse.createSuccessWithNoContent("핸드폰 번호 차단 성공")); - } - - @GetMapping("") - @Operation(summary = "핸드폰 번호 차단", description = "핸드폰 번호 리스트를 전달받고, 전달받은 핸드폰 번호 차단을 수행합니다.", tags = {"차단"}) - @ApiResponse(responseCode = "200", description = "핸드폰 차단 성공") - public ResponseEntity> blockPhoneNumbers(@AuthenticationPrincipal Long userId) { - List blocks = blockService.findBlocksByUserId(userId); - return ResponseEntity.status(HttpStatus.OK).body(CommonResponse.createSuccess(UserBlockResponses.from(userId, blocks))); - } -} diff --git a/api/src/main/java/org/yapp/domain/block/presentation/dto/response/BlockResponse.java b/api/src/main/java/org/yapp/domain/block/presentation/dto/response/BlockContactResponse.java similarity index 52% rename from api/src/main/java/org/yapp/domain/block/presentation/dto/response/BlockResponse.java rename to api/src/main/java/org/yapp/domain/block/presentation/dto/response/BlockContactResponse.java index 468de9d..32a0af2 100644 --- a/api/src/main/java/org/yapp/domain/block/presentation/dto/response/BlockResponse.java +++ b/api/src/main/java/org/yapp/domain/block/presentation/dto/response/BlockContactResponse.java @@ -2,5 +2,6 @@ import java.time.LocalDateTime; -public record BlockResponse(String phoneNumber, LocalDateTime blockedAt) { +public record BlockContactResponse(String phoneNumber, LocalDateTime blockedAt) { + } diff --git a/api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockContactResponses.java b/api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockContactResponses.java new file mode 100644 index 0000000..534a839 --- /dev/null +++ b/api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockContactResponses.java @@ -0,0 +1,20 @@ +package org.yapp.domain.block.presentation.dto.response; + +import java.util.List; +import org.yapp.domain.block.BlockContact; + +public record UserBlockContactResponses(Long userId, + List blockContactResponses) { + + public static UserBlockContactResponses from(Long userId, List blockContacts) { + List blockContactResponses = blockContacts.stream().map( + blockContact -> new BlockContactResponse(blockContact.getPhoneNumber(), + blockContact.getCreatedAt())).toList(); + + return new UserBlockContactResponses( + userId, + blockContactResponses + ); + } + +} diff --git a/api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockResponses.java b/api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockResponses.java deleted file mode 100644 index 05bde3a..0000000 --- a/api/src/main/java/org/yapp/domain/block/presentation/dto/response/UserBlockResponses.java +++ /dev/null @@ -1,17 +0,0 @@ -package org.yapp.domain.block.presentation.dto.response; - -import org.yapp.domain.block.Block; - -import java.util.List; - -public record UserBlockResponses (Long userId, List blockResponses) { - public static UserBlockResponses from (Long userId, List blocks) { - List blockResponses = blocks.stream().map(block -> new BlockResponse(block.getPhoneNumber(), block.getCreatedAt())).toList(); - - return new UserBlockResponses( - userId, - blockResponses - ); - } - -} diff --git a/common/domain/src/main/java/org/yapp/domain/block/Block.java b/common/domain/src/main/java/org/yapp/domain/block/BlockContact.java similarity index 96% rename from common/domain/src/main/java/org/yapp/domain/block/Block.java rename to common/domain/src/main/java/org/yapp/domain/block/BlockContact.java index f1400b4..c7cf114 100644 --- a/common/domain/src/main/java/org/yapp/domain/block/Block.java +++ b/common/domain/src/main/java/org/yapp/domain/block/BlockContact.java @@ -31,7 +31,7 @@ @Index(name = "idx_phone_number", columnList = "phoneNumber"), } ) -public class Block extends BaseEntity { +public class BlockContact extends BaseEntity { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) From 3a500dc1dc701eb35dfe9b82f14365afbeac7e0a Mon Sep 17 00:00:00 2001 From: LujaeC Date: Tue, 21 Jan 2025 01:19:20 +0900 Subject: [PATCH 25/38] =?UTF-8?q?[PC-383]=20feat:=20=EC=B0=A8=EB=8B=A8=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/application/UserBlockService.java | 53 +++++++++++++++++++ .../yapp/block/dao/UserBlockRepository.java | 10 ++++ .../presentation/UserBlockController.java | 31 +++++++++++ .../response/UserBlockResponse.java | 12 +++++ .../java/org/yapp/domain/block/UserBlock.java | 37 +++++++++++++ 5 files changed, 143 insertions(+) create mode 100644 admin/src/main/java/org/yapp/block/application/UserBlockService.java create mode 100644 admin/src/main/java/org/yapp/block/dao/UserBlockRepository.java create mode 100644 admin/src/main/java/org/yapp/block/presentation/UserBlockController.java create mode 100644 admin/src/main/java/org/yapp/block/presentation/response/UserBlockResponse.java create mode 100644 common/domain/src/main/java/org/yapp/domain/block/UserBlock.java diff --git a/admin/src/main/java/org/yapp/block/application/UserBlockService.java b/admin/src/main/java/org/yapp/block/application/UserBlockService.java new file mode 100644 index 0000000..0172f2b --- /dev/null +++ b/admin/src/main/java/org/yapp/block/application/UserBlockService.java @@ -0,0 +1,53 @@ +package org.yapp.block.application; + +import java.util.List; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.stereotype.Service; +import org.yapp.block.dao.UserBlockRepository; +import org.yapp.block.presentation.response.UserBlockResponse; +import org.yapp.domain.block.UserBlock; +import org.yapp.domain.user.User; +import org.yapp.util.PageResponse; + +@Service +@RequiredArgsConstructor +public class UserBlockService { + + private final UserBlockRepository userBlockRepository; + + public PageResponse getUserBlockPageResponse(int page, int size) { + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + + Page userBlockPage = userBlockRepository.findAll(pageable); + + List content = userBlockPage.getContent().stream() + .map(userBlock -> { + User blockingUser = userBlock.getBlockingUser(); + User blockedUser = userBlock.getBlockedUser(); + + return new UserBlockResponse( + blockedUser.getId(), + blockedUser.getProfile().getProfileBasic().getNickname(), + blockedUser.getName(), + blockedUser.getProfile().getProfileBasic().getBirthdate(), + blockingUser.getId(), + blockingUser.getProfile().getProfileBasic().getNickname(), + blockingUser.getName(), + userBlock.getCreatedAt().toLocalDate()); + }).toList(); + + return new PageResponse<>( + content, + userBlockPage.getNumber(), + userBlockPage.getSize(), + userBlockPage.getTotalPages(), + userBlockPage.getTotalElements(), + userBlockPage.isFirst(), + userBlockPage.isLast() + ); + } +} diff --git a/admin/src/main/java/org/yapp/block/dao/UserBlockRepository.java b/admin/src/main/java/org/yapp/block/dao/UserBlockRepository.java new file mode 100644 index 0000000..b2dc02f --- /dev/null +++ b/admin/src/main/java/org/yapp/block/dao/UserBlockRepository.java @@ -0,0 +1,10 @@ +package org.yapp.block.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; +import org.yapp.domain.block.UserBlock; + +@Repository +public interface UserBlockRepository extends JpaRepository { + +} diff --git a/admin/src/main/java/org/yapp/block/presentation/UserBlockController.java b/admin/src/main/java/org/yapp/block/presentation/UserBlockController.java new file mode 100644 index 0000000..28e25ac --- /dev/null +++ b/admin/src/main/java/org/yapp/block/presentation/UserBlockController.java @@ -0,0 +1,31 @@ +package org.yapp.block.presentation; + +import lombok.RequiredArgsConstructor; +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.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.yapp.block.application.UserBlockService; +import org.yapp.block.presentation.response.UserBlockResponse; +import org.yapp.util.CommonResponse; +import org.yapp.util.PageResponse; + +@RestController() +@RequiredArgsConstructor +@RequestMapping("/admin/v1/blocks") +public class UserBlockController { + + private final UserBlockService userBlockService; + + @GetMapping("") + public ResponseEntity>> getUsers( + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { + + PageResponse userBlockPageResponse = userBlockService.getUserBlockPageResponse( + page, size); + + return ResponseEntity.ok(CommonResponse.createSuccess(userBlockPageResponse)); + } +} diff --git a/admin/src/main/java/org/yapp/block/presentation/response/UserBlockResponse.java b/admin/src/main/java/org/yapp/block/presentation/response/UserBlockResponse.java new file mode 100644 index 0000000..d49c282 --- /dev/null +++ b/admin/src/main/java/org/yapp/block/presentation/response/UserBlockResponse.java @@ -0,0 +1,12 @@ +package org.yapp.block.presentation.response; + +import java.time.LocalDate; + +public record UserBlockResponse( + Long blockedUserId, + String BlockedUserNickname, String BlockedUserName, + LocalDate blockedUserBirthdate, Long blockingUserId, + String blockingUserNickname, + String blockingUserName, LocalDate BlockedDate) { + +} diff --git a/common/domain/src/main/java/org/yapp/domain/block/UserBlock.java b/common/domain/src/main/java/org/yapp/domain/block/UserBlock.java new file mode 100644 index 0000000..df1d1ea --- /dev/null +++ b/common/domain/src/main/java/org/yapp/domain/block/UserBlock.java @@ -0,0 +1,37 @@ +package org.yapp.domain.block; + + +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.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.yapp.domain.BaseEntity; +import org.yapp.domain.user.User; + +@Entity +@Builder +@Getter +@AllArgsConstructor +@NoArgsConstructor +public class UserBlock extends BaseEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Column(name = "user_block_id") + private Long id; + + @ManyToOne + @JoinColumn(name = "blocking_user_id", nullable = false) + private User BlockingUser; + + @ManyToOne + @JoinColumn(name = "blocked_user_id", nullable = false) + private User BlockedUser; +} From 42cdd4f5b1841a8ac1a71701b0a42347d9654616 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Tue, 21 Jan 2025 01:19:35 +0900 Subject: [PATCH 26/38] =?UTF-8?q?[PC-383]=20feat:=20=EC=B0=A8=EB=8B=A8=20?= =?UTF-8?q?=EB=8D=94=EB=AF=B8=20=EB=8D=B0=EC=9D=B4=ED=84=B0=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 --- api/src/main/resources/init.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/api/src/main/resources/init.sql b/api/src/main/resources/init.sql index 9f360cb..362f2d4 100644 --- a/api/src/main/resources/init.sql +++ b/api/src/main/resources/init.sql @@ -71,6 +71,12 @@ VALUES (11, 3, 2, '부적절한 언어 사용 2222', NOW(), NOW()); INSERT INTO report (report_id, reporter_user_id, reported_user_id, reason, created_at, updated_at) VALUES (12, 1, 2, '부적절한 언어 사용 3333', NOW(), NOW()); +INSERT INTO user_block (user_block_id, blocking_user_id, blocked_user_id, created_at, updated_at) +VALUES (1, 1, 2, NOW(), NOW()), + (2, 2, 3, NOW(), NOW()), + (3, 3, 4, NOW(), NOW()), + (4, 4, 1, NOW(), NOW()), + (5, 1, 3, NOW(), NOW()); -- ValueItem 더미 데이터 삽입 INSERT INTO value_pick (value_pick_id, category, question, answers, is_active) From c62fb0bad1a5ee09e970cbc74bb9afff874c58cc Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 19:52:14 +0900 Subject: [PATCH 27/38] =?UTF-8?q?[PC-382]=20fix:=20RoleStatus=20=ED=8C=A8?= =?UTF-8?q?=ED=82=A4=EC=A7=80=20=EC=9C=84=EC=B9=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/auth/application/oauth/service/OauthService.java | 2 +- .../org/yapp/domain/profile/application/ProfileService.java | 2 +- .../main/java/org/yapp/domain/user/application/UserService.java | 2 +- .../domain/src/main/java/org/yapp/domain/user}/RoleStatus.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename {api/src/main/java/org/yapp/domain/auth/presentation/dto/enums => common/domain/src/main/java/org/yapp/domain/user}/RoleStatus.java (85%) diff --git a/api/src/main/java/org/yapp/domain/auth/application/oauth/service/OauthService.java b/api/src/main/java/org/yapp/domain/auth/application/oauth/service/OauthService.java index dec7aed..0c0277d 100644 --- a/api/src/main/java/org/yapp/domain/auth/application/oauth/service/OauthService.java +++ b/api/src/main/java/org/yapp/domain/auth/application/oauth/service/OauthService.java @@ -6,9 +6,9 @@ import org.yapp.domain.auth.application.jwt.JwtUtil; import org.yapp.domain.auth.application.oauth.OauthProvider; import org.yapp.domain.auth.application.oauth.OauthProviderResolver; -import org.yapp.domain.auth.presentation.dto.enums.RoleStatus; import org.yapp.domain.auth.presentation.dto.request.OauthLoginRequest; import org.yapp.domain.auth.presentation.dto.response.OauthLoginResponse; +import org.yapp.domain.user.RoleStatus; import org.yapp.domain.user.User; import org.yapp.domain.user.dao.UserRepository; diff --git a/api/src/main/java/org/yapp/domain/profile/application/ProfileService.java b/api/src/main/java/org/yapp/domain/profile/application/ProfileService.java index 5b6de76..70ce1ab 100644 --- a/api/src/main/java/org/yapp/domain/profile/application/ProfileService.java +++ b/api/src/main/java/org/yapp/domain/profile/application/ProfileService.java @@ -7,7 +7,6 @@ import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.yapp.domain.auth.presentation.dto.enums.RoleStatus; import org.yapp.domain.profile.Profile; import org.yapp.domain.profile.ProfileBasic; import org.yapp.domain.profile.ProfileValuePick; @@ -19,6 +18,7 @@ import org.yapp.domain.profile.presentation.request.ProfileValuePickUpdateRequest.ProfileValuePickPair; import org.yapp.domain.profile.presentation.request.ProfileValueTalkUpdateRequest; import org.yapp.domain.profile.presentation.request.ProfileValueTalkUpdateRequest.ProfileValueTalkPair; +import org.yapp.domain.user.RoleStatus; import org.yapp.domain.user.User; import org.yapp.domain.user.application.UserService; import org.yapp.error.dto.ProfileErrorCode; diff --git a/api/src/main/java/org/yapp/domain/user/application/UserService.java b/api/src/main/java/org/yapp/domain/user/application/UserService.java index cc7b6ef..f6153d4 100644 --- a/api/src/main/java/org/yapp/domain/user/application/UserService.java +++ b/api/src/main/java/org/yapp/domain/user/application/UserService.java @@ -5,9 +5,9 @@ import org.springframework.transaction.annotation.Transactional; import org.yapp.application.AuthenticationService; import org.yapp.domain.auth.application.jwt.JwtUtil; -import org.yapp.domain.auth.presentation.dto.enums.RoleStatus; import org.yapp.domain.auth.presentation.dto.response.OauthLoginResponse; import org.yapp.domain.profile.Profile; +import org.yapp.domain.user.RoleStatus; import org.yapp.domain.user.User; import org.yapp.domain.user.dao.UserRepository; import org.yapp.error.dto.UserErrorCode; diff --git a/api/src/main/java/org/yapp/domain/auth/presentation/dto/enums/RoleStatus.java b/common/domain/src/main/java/org/yapp/domain/user/RoleStatus.java similarity index 85% rename from api/src/main/java/org/yapp/domain/auth/presentation/dto/enums/RoleStatus.java rename to common/domain/src/main/java/org/yapp/domain/user/RoleStatus.java index 192f4c0..35d1b71 100644 --- a/api/src/main/java/org/yapp/domain/auth/presentation/dto/enums/RoleStatus.java +++ b/common/domain/src/main/java/org/yapp/domain/user/RoleStatus.java @@ -1,4 +1,4 @@ -package org.yapp.domain.auth.presentation.dto.enums; +package org.yapp.domain.user; import com.fasterxml.jackson.annotation.JsonValue; import lombok.AllArgsConstructor; From bec314926514e93c2efb24dc15f255067afb5301 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 20:12:33 +0900 Subject: [PATCH 28/38] =?UTF-8?q?[PC-382]=20fix:=20ManyToOne=20=EA=B4=80?= =?UTF-8?q?=EA=B3=84=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 --- .../java/org/yapp/domain/profile/ProfileRejectHistory.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java b/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java index 392b4ae..c182028 100644 --- a/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java +++ b/common/domain/src/main/java/org/yapp/domain/profile/ProfileRejectHistory.java @@ -2,11 +2,12 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.FetchType; import jakarta.persistence.GeneratedValue; import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; -import jakarta.persistence.OneToOne; +import jakarta.persistence.ManyToOne; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; @@ -26,7 +27,7 @@ public class ProfileRejectHistory extends BaseEntity { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @OneToOne() + @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id") private User user; From 986e18295d5eec82265c946ac8ff155c2e169306 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 20:30:11 +0900 Subject: [PATCH 29/38] =?UTF-8?q?[PC-382]=20fix:=20response=20=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95=20(reason?= =?UTF-8?q?=20->=20reject)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../response/UserProfileValidationResponse.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java index 5e3bbae..a02e948 100644 --- a/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java +++ b/admin/src/main/java/org/yapp/user/presentation/response/UserProfileValidationResponse.java @@ -10,11 +10,11 @@ public record UserProfileValidationResponse(Long userId, String description, String nickname, String name, LocalDate birthdate, String phoneNumber, LocalDate joinDate, - String profileStatus, boolean reasonImage, - boolean reasonDescription) { + String profileStatus, boolean rejectImage, + boolean rejectDescription) { - public static UserProfileValidationResponse from(User user, boolean reasonImage, - boolean reasonDescription) { + public static UserProfileValidationResponse from(User user, boolean rejectImage, + boolean rejectDescription) { Profile profile = user.getProfile(); return UserProfileValidationResponse.builder() @@ -26,8 +26,8 @@ public static UserProfileValidationResponse from(User user, boolean reasonImage, .phoneNumber(user.getPhoneNumber() != null ? user.getPhoneNumber() : null) .joinDate(user.getCreatedAt() != null ? user.getCreatedAt().toLocalDate() : null) .profileStatus(profile != null ? profile.getProfileStatus().getDisplayName() : null) - .reasonImage(reasonImage) - .reasonDescription(reasonDescription) + .rejectImage(rejectImage) + .rejectDescription(rejectDescription) .build(); } } From ff5eb5072948bbd25a8ae29ef0608cf963dec748 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 20:30:39 +0900 Subject: [PATCH 30/38] =?UTF-8?q?[PC-382]=20feat:=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EC=9C=A0=EC=A0=80=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../application/AdminProfileService.java | 53 +++++++++++++++++++ .../user/presentation/UserController.java | 18 ++++++- .../java/org/yapp/domain/profile/Profile.java | 4 ++ 3 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 admin/src/main/java/org/yapp/profile/application/AdminProfileService.java diff --git a/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java b/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java new file mode 100644 index 0000000..c0ae7ca --- /dev/null +++ b/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java @@ -0,0 +1,53 @@ +package org.yapp.profile.application; + +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.yapp.domain.profile.Profile; +import org.yapp.domain.profile.ProfileRejectHistory; +import org.yapp.domain.profile.ProfileStatus; +import org.yapp.domain.user.RoleStatus; +import org.yapp.domain.user.User; +import org.yapp.error.dto.ProfileErrorCode; +import org.yapp.error.exception.ApplicationException; +import org.yapp.profile.dao.ProfileRejectHistoryRepository; +import org.yapp.user.application.UserService; + +@Service +@RequiredArgsConstructor +public class AdminProfileService { + + private final ProfileRejectHistoryRepository profileRejectHistoryRepository; + private final UserService userService; + + @Transactional + public void updateProfileStatus(Long userId, boolean reasonImage, boolean reasonDescription) { + User user = userService.getUserById(userId); + Profile profile = user.getProfile(); + + if (profile == null) { + throw new ApplicationException(ProfileErrorCode.NOTFOUND_PROFILE); + } + + if (reasonImage || reasonDescription) { + rejectProfile(user.getProfile(), reasonImage, reasonDescription); + } else { + passProfile(profile); + } + } + + private void rejectProfile(Profile profile, boolean reasonImage, boolean reasonDescription) { + profileRejectHistoryRepository.save(ProfileRejectHistory.builder() + .user(profile.getUser()) + .reasonImage(reasonImage) + .reasonDescription(reasonDescription) + .build()); + + profile.updateProfileStatus(ProfileStatus.REJECTED); + } + + private void passProfile(Profile profile) { + profile.updateProfileStatus(ProfileStatus.APPROVED); + profile.getUser().updateUserRole(RoleStatus.USER.getStatus()); + } +} diff --git a/admin/src/main/java/org/yapp/user/presentation/UserController.java b/admin/src/main/java/org/yapp/user/presentation/UserController.java index ab6fcd7..ad35f04 100644 --- a/admin/src/main/java/org/yapp/user/presentation/UserController.java +++ b/admin/src/main/java/org/yapp/user/presentation/UserController.java @@ -1,12 +1,16 @@ package org.yapp.user.presentation; +import jakarta.validation.Valid; import lombok.RequiredArgsConstructor; import org.springframework.http.ResponseEntity; 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.RequestParam; import org.springframework.web.bind.annotation.RestController; +import org.yapp.profile.application.AdminProfileService; import org.yapp.user.application.UserService; import org.yapp.user.presentation.response.UserProfileDetailResponses; import org.yapp.user.presentation.response.UserProfileValidationResponse; @@ -19,6 +23,7 @@ public class UserController { private final UserService userService; + private final AdminProfileService adminProfileService; @GetMapping("") public ResponseEntity>> getUsers( @@ -33,9 +38,20 @@ public ResponseEntity @GetMapping("/{userId}") public ResponseEntity> getUserProfile( - @PathVariable long userId) { + @PathVariable Long userId) { UserProfileDetailResponses userProfileDetails = userService.getUserProfileDetails(userId); return ResponseEntity.ok(CommonResponse.createSuccess(userProfileDetails)); } + + @PostMapping("/{userId}/profile") + public ResponseEntity> updateUserProfileStatus( + @PathVariable Long userId, + @RequestBody @Valid UpdateProfileStatusRequest request) { + + adminProfileService.updateProfileStatus(userId, request.rejectImage(), + request.rejectDescription()); + + return ResponseEntity.ok(CommonResponse.createSuccess(null)); + } } diff --git a/common/domain/src/main/java/org/yapp/domain/profile/Profile.java b/common/domain/src/main/java/org/yapp/domain/profile/Profile.java index df1b562..2c0d53f 100644 --- a/common/domain/src/main/java/org/yapp/domain/profile/Profile.java +++ b/common/domain/src/main/java/org/yapp/domain/profile/Profile.java @@ -68,4 +68,8 @@ public void updateProfileValuePicks(List profileValuePicks) { public void updateProfileValueTalks(List profileValueTalks) { this.profileValueTalks = profileValueTalks; } + + public void updateProfileStatus(ProfileStatus profileStatus) { + this.profileStatus = profileStatus; + } } From 1ec6d93606eb79e2d2fb281cca1dc2d25f20cfee Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 20:30:42 +0900 Subject: [PATCH 31/38] =?UTF-8?q?[PC-382]=20feat:=20=EA=B4=80=EB=A6=AC?= =?UTF-8?q?=EC=9E=90=20=EC=9C=A0=EC=A0=80=20=ED=94=84=EB=A1=9C=ED=95=84=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=88=98=EC=A0=95=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/presentation/UpdateProfileStatusRequest.java | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 admin/src/main/java/org/yapp/user/presentation/UpdateProfileStatusRequest.java diff --git a/admin/src/main/java/org/yapp/user/presentation/UpdateProfileStatusRequest.java b/admin/src/main/java/org/yapp/user/presentation/UpdateProfileStatusRequest.java new file mode 100644 index 0000000..c74d1c2 --- /dev/null +++ b/admin/src/main/java/org/yapp/user/presentation/UpdateProfileStatusRequest.java @@ -0,0 +1,8 @@ +package org.yapp.user.presentation; + +import jakarta.validation.constraints.NotNull; + +public record UpdateProfileStatusRequest(@NotNull boolean rejectImage, + @NotNull boolean rejectDescription) { + +} From fadde4fe90ee43b18e122b17341334ef7ff90d40 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 20:33:29 +0900 Subject: [PATCH 32/38] =?UTF-8?q?[PC-382]=20feat:=20=EB=A6=AC=EC=A0=9D=20?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B2=BD=EC=9A=B0=20=EB=A9=A4=EB=B2=84=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20PENDING=EC=9C=BC=EB=A1=9C=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 --- .../java/org/yapp/profile/application/AdminProfileService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java b/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java index c0ae7ca..0d98dee 100644 --- a/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java +++ b/admin/src/main/java/org/yapp/profile/application/AdminProfileService.java @@ -44,6 +44,7 @@ private void rejectProfile(Profile profile, boolean reasonImage, boolean reasonD .build()); profile.updateProfileStatus(ProfileStatus.REJECTED); + profile.getUser().updateUserRole(RoleStatus.PENDING.getStatus()); } private void passProfile(Profile profile) { From aee284c2c3d3046daad3ff74c7db9f24f46ab8e9 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 22:26:28 +0900 Subject: [PATCH 33/38] =?UTF-8?q?[PC-379]=20fix:=20auth=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/build.gradle | 3 +- .../main/java/org/yapp/auth/AuthToken.java | 5 ++ .../org/yapp/auth/AuthTokenGenerator.java | 30 +++++++ .../src/main/java/org/yapp/jwt/JwtFilter.java | 68 ++++++++++++++ .../src/main/java/org/yapp/jwt/JwtUtil.java | 89 +++++++++++++++++++ settings.gradle | 2 + 6 files changed, 196 insertions(+), 1 deletion(-) create mode 100644 common/auth/src/main/java/org/yapp/auth/AuthToken.java create mode 100644 common/auth/src/main/java/org/yapp/auth/AuthTokenGenerator.java create mode 100644 common/auth/src/main/java/org/yapp/jwt/JwtFilter.java create mode 100644 common/auth/src/main/java/org/yapp/jwt/JwtUtil.java diff --git a/admin/build.gradle b/admin/build.gradle index 5c74e14..fd1696b 100644 --- a/admin/build.gradle +++ b/admin/build.gradle @@ -13,7 +13,8 @@ dependencies { implementation project(':common:domain') implementation project(':common:format') implementation project(':common:exception') - + implementation project(':common:auth') + testImplementation platform('org.junit:junit-bom:5.10.0') testImplementation 'org.junit.jupiter:junit-jupiter' } diff --git a/common/auth/src/main/java/org/yapp/auth/AuthToken.java b/common/auth/src/main/java/org/yapp/auth/AuthToken.java new file mode 100644 index 0000000..8ec9d57 --- /dev/null +++ b/common/auth/src/main/java/org/yapp/auth/AuthToken.java @@ -0,0 +1,5 @@ +package org.yapp.auth; + +public record AuthToken(String accessToken, String refreshToken) { + +} diff --git a/common/auth/src/main/java/org/yapp/auth/AuthTokenGenerator.java b/common/auth/src/main/java/org/yapp/auth/AuthTokenGenerator.java new file mode 100644 index 0000000..fd6778e --- /dev/null +++ b/common/auth/src/main/java/org/yapp/auth/AuthTokenGenerator.java @@ -0,0 +1,30 @@ +package org.yapp.auth; + +import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.yapp.jwt.JwtUtil; + +@Component +@RequiredArgsConstructor +public class AuthTokenGenerator { + + private final JwtUtil jwtUtil; + + @Value("${jwt.accessToken.expiration}") + private Long accessTokenExpiration; + + @Value("${jwt.refreshToken.expiration}") + private Long refreshTokenExpiration; + + + public AuthToken generate(Long userId, String oauthId, String role) { + String accessToken = jwtUtil.createJwt("access_token", userId, oauthId, role, + accessTokenExpiration); + + String refreshToken = jwtUtil.createJwt("refesh_token", userId, oauthId, role, + refreshTokenExpiration); + + return new AuthToken(accessToken, refreshToken); + } +} diff --git a/common/auth/src/main/java/org/yapp/jwt/JwtFilter.java b/common/auth/src/main/java/org/yapp/jwt/JwtFilter.java new file mode 100644 index 0000000..4d0ac2b --- /dev/null +++ b/common/auth/src/main/java/org/yapp/jwt/JwtFilter.java @@ -0,0 +1,68 @@ +package org.yapp.jwt; + +import io.jsonwebtoken.ExpiredJwtException; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.Collections; +import lombok.RequiredArgsConstructor; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; +import org.springframework.web.filter.OncePerRequestFilter; + +@RequiredArgsConstructor +@Component +public class JwtFilter extends OncePerRequestFilter { + + private final JwtUtil jwtUtil; + + @Override + protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, + FilterChain filterChain) + throws ServletException, IOException { + + String accessToken = request.getHeader("Authorization"); + if (accessToken == null || !accessToken.startsWith("Bearer ")) { + filterChain.doFilter(request, response); + return; + } + accessToken = accessToken.substring(7); + + try { + jwtUtil.isExpired(accessToken); + } catch (ExpiredJwtException e) { + + PrintWriter writer = response.getWriter(); + writer.print("access token expired"); + + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + String category = jwtUtil.getCategory(accessToken); + if (!category.equals("access_token")) { + PrintWriter writer = response.getWriter(); + writer.print("invalid access token"); + + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + return; + } + + Long userId = jwtUtil.getUserId(accessToken); + String role = jwtUtil.getRole(accessToken); + + Authentication authToken = + new UsernamePasswordAuthenticationToken(userId, null, Collections.singleton( + (GrantedAuthority) () -> role)); + + SecurityContextHolder.getContext().setAuthentication(authToken); + + filterChain.doFilter(request, response); + } +} diff --git a/common/auth/src/main/java/org/yapp/jwt/JwtUtil.java b/common/auth/src/main/java/org/yapp/jwt/JwtUtil.java new file mode 100644 index 0000000..1db9c7f --- /dev/null +++ b/common/auth/src/main/java/org/yapp/jwt/JwtUtil.java @@ -0,0 +1,89 @@ +package org.yapp.jwt; + +import io.jsonwebtoken.Jwts; +import java.nio.charset.StandardCharsets; +import java.util.Date; +import javax.crypto.SecretKey; +import javax.crypto.spec.SecretKeySpec; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +@Component +public class JwtUtil { + + private final SecretKey secretKey; + + public JwtUtil(@Value("${jwt.secret}") String secret) { + secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), + Jwts.SIG.HS256.key().build().getAlgorithm()); + } + + public String getOauthId(String token) { + String oauthId; + try { + oauthId = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token) + .getPayload().get("oauthId", String.class); + } catch (Exception e) { + throw new RuntimeException(); + } + return oauthId; + } + + public String getRole(String token) { + String role; + try { + role = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token).getPayload() + .get("role", String.class); + } catch (Exception e) { + throw new RuntimeException(); + } + return role; + } + + public Boolean isExpired(String token) { + boolean before; + try { + before = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token) + .getPayload().getExpiration().before(new Date()); + } catch (Exception e) { + throw new RuntimeException(); + } + return before; + } + + public String createJwt(String category, Long userId, String oauthId, String role, + Long expiredMs) { + return Jwts.builder() + .claim("category", category) + .claim("userId", userId) + .claim("oauthId", oauthId) + .claim("role", role) + .issuedAt(new Date(System.currentTimeMillis())) + .expiration(new Date(System.currentTimeMillis() + expiredMs)) + .signWith(secretKey) + .compact(); + } + + public Long getUserId(String token) { + Long userId; + try { + userId = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token) + .getPayload().get("userId", Long.class); + } catch (Exception e) { + throw new RuntimeException(); + } + return userId; + } + + public String getCategory(String token) { + String category; + try { + category = Jwts.parser().verifyWith(secretKey).build().parseSignedClaims(token) + .getPayload().get("category", String.class); + } catch (Exception e) { + throw new RuntimeException(); + } + return category; + } +} + diff --git a/settings.gradle b/settings.gradle index d3c3d28..6b03748 100644 --- a/settings.gradle +++ b/settings.gradle @@ -8,4 +8,6 @@ include 'common:exception' findProject(':common:exception')?.name = 'exception' include 'common:format' findProject(':common:format')?.name = 'format' +include 'common:auth' +findProject(':common:auth')?.name = 'auth' From af3bfa28585975e151ebe66ffafb7db33d0c642c Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 22:27:28 +0900 Subject: [PATCH 34/38] =?UTF-8?q?[PC-379]=20feat:=20admin=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20oauthId=20=EA=B8=B0=EB=B0=98=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/org/yapp/user/application/UserService.java | 5 +++++ admin/src/main/java/org/yapp/user/dao/UserRepository.java | 2 ++ 2 files changed, 7 insertions(+) diff --git a/admin/src/main/java/org/yapp/user/application/UserService.java b/admin/src/main/java/org/yapp/user/application/UserService.java index c206404..2e479f2 100644 --- a/admin/src/main/java/org/yapp/user/application/UserService.java +++ b/admin/src/main/java/org/yapp/user/application/UserService.java @@ -36,6 +36,11 @@ public User getUserById(Long userId) { .orElseThrow(() -> new ApplicationException(UserErrorCode.NOTFOUND_USER)); } + public User getUserByOauthId(String oauthId) { + return userRepository.findByOauthId(oauthId) + .orElseThrow(() -> new ApplicationException(UserErrorCode.NOTFOUND_USER)); + } + public PageResponse getUserProfilesWithPagination(int page, int size) { Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); diff --git a/admin/src/main/java/org/yapp/user/dao/UserRepository.java b/admin/src/main/java/org/yapp/user/dao/UserRepository.java index ce89bd9..e1d19a8 100644 --- a/admin/src/main/java/org/yapp/user/dao/UserRepository.java +++ b/admin/src/main/java/org/yapp/user/dao/UserRepository.java @@ -9,4 +9,6 @@ public interface UserRepository extends JpaRepository { Optional findById(Long userId); + + Optional findByOauthId(String oauthId); } From 13edacc873d97f48390068dd306f3bbc3b3d01dc Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 22:27:47 +0900 Subject: [PATCH 35/38] =?UTF-8?q?[PC-379]=20feat:=20admin=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20jwt=20=ED=95=84=ED=84=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/main/java/org/yapp/config/SecurityConfig.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/admin/src/main/java/org/yapp/config/SecurityConfig.java b/admin/src/main/java/org/yapp/config/SecurityConfig.java index 2f50146..eaf19e0 100644 --- a/admin/src/main/java/org/yapp/config/SecurityConfig.java +++ b/admin/src/main/java/org/yapp/config/SecurityConfig.java @@ -11,16 +11,20 @@ import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.security.web.util.matcher.RequestMatchers; import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.CorsConfigurationSource; +import org.yapp.jwt.JwtFilter; @Configuration @EnableWebSecurity @RequiredArgsConstructor public class SecurityConfig { + private final JwtFilter jwtFilter; + @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { return http.csrf(AbstractHttpConfigurer::disable) @@ -33,6 +37,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti .permitAll() .anyRequest() .hasAnyRole("ADMIN")) + .addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class) .build(); } @@ -47,6 +52,6 @@ private CorsConfigurationSource corsConfigurationSource() { } private RequestMatcher getMatcherForAnyone() { - return RequestMatchers.anyOf(antMatcher("/admin/v1/login/**")); + return RequestMatchers.anyOf(antMatcher("/admin/v1/auth/login/**")); } } \ No newline at end of file From da942bcdb04d0372826056d9278ad384484034e8 Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 22:28:19 +0900 Subject: [PATCH 36/38] =?UTF-8?q?[PC-379]=20feat:=20admin=20=EB=AA=A8?= =?UTF-8?q?=EB=93=88=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B8=B0=EB=8A=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/yapp/auth/application/AdminRole.java | 6 +++ .../yapp/auth/application/AuthService.java | 40 +++++++++++++++++++ .../yapp/auth/application/dto/LoginDto.java | 5 +++ .../auth/presentation/AuthController.java | 28 +++++++++++++ .../presentation/request/LoginRequest.java | 11 +++++ admin/src/main/resources/application.yml | 2 +- .../yapp/error/code/auth/AuthErrorCode.java | 2 + 7 files changed, 93 insertions(+), 1 deletion(-) create mode 100644 admin/src/main/java/org/yapp/auth/application/AdminRole.java create mode 100644 admin/src/main/java/org/yapp/auth/application/AuthService.java create mode 100644 admin/src/main/java/org/yapp/auth/application/dto/LoginDto.java create mode 100644 admin/src/main/java/org/yapp/auth/presentation/AuthController.java create mode 100644 admin/src/main/java/org/yapp/auth/presentation/request/LoginRequest.java diff --git a/admin/src/main/java/org/yapp/auth/application/AdminRole.java b/admin/src/main/java/org/yapp/auth/application/AdminRole.java new file mode 100644 index 0000000..bb44eac --- /dev/null +++ b/admin/src/main/java/org/yapp/auth/application/AdminRole.java @@ -0,0 +1,6 @@ +package org.yapp.auth.application; + +public enum AdminRole { + ADMIN, + ROLE_ADMIN; +} diff --git a/admin/src/main/java/org/yapp/auth/application/AuthService.java b/admin/src/main/java/org/yapp/auth/application/AuthService.java new file mode 100644 index 0000000..b361d9c --- /dev/null +++ b/admin/src/main/java/org/yapp/auth/application/AuthService.java @@ -0,0 +1,40 @@ +package org.yapp.auth.application; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; +import org.yapp.auth.AuthToken; +import org.yapp.auth.AuthTokenGenerator; +import org.yapp.auth.application.dto.LoginDto; +import org.yapp.domain.user.User; +import org.yapp.error.code.auth.AuthErrorCode; +import org.yapp.error.exception.ApplicationException; +import org.yapp.user.application.UserService; + +@Slf4j +@Service +@RequiredArgsConstructor +public class AuthService { + + private final UserService userService; + + private final AuthTokenGenerator authTokenGenerator; + + @Value("${admin.password}") + private String PWD; + + public AuthToken login(LoginDto loginDto) { + String oauthId = loginDto.oauthId(); + String password = loginDto.password(); + + User loginUser = userService.getUserByOauthId(oauthId); + + if (password.equals(PWD) && loginUser.getRole().equals(AdminRole.ADMIN.toString())) { + return authTokenGenerator.generate(loginUser.getId(), null, + AdminRole.ROLE_ADMIN.toString()); + } else { + throw new ApplicationException(AuthErrorCode.ACCESS_DENIED); + } + } +} diff --git a/admin/src/main/java/org/yapp/auth/application/dto/LoginDto.java b/admin/src/main/java/org/yapp/auth/application/dto/LoginDto.java new file mode 100644 index 0000000..232153a --- /dev/null +++ b/admin/src/main/java/org/yapp/auth/application/dto/LoginDto.java @@ -0,0 +1,5 @@ +package org.yapp.auth.application.dto; + +public record LoginDto(String oauthId, String password) { + +} diff --git a/admin/src/main/java/org/yapp/auth/presentation/AuthController.java b/admin/src/main/java/org/yapp/auth/presentation/AuthController.java new file mode 100644 index 0000000..84d20c6 --- /dev/null +++ b/admin/src/main/java/org/yapp/auth/presentation/AuthController.java @@ -0,0 +1,28 @@ +package org.yapp.auth.presentation; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +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; +import org.yapp.auth.AuthToken; +import org.yapp.auth.application.AuthService; +import org.yapp.auth.presentation.request.LoginRequest; +import org.yapp.util.CommonResponse; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/admin/v1/auth/") +public class AuthController { + + private final AuthService authService; + + @PostMapping("/login") + public ResponseEntity> login( + @RequestBody @Valid LoginRequest loginRequest) { + AuthToken authToken = authService.login(loginRequest.toDto()); + return ResponseEntity.ok(CommonResponse.createSuccess(authToken)); + } +} diff --git a/admin/src/main/java/org/yapp/auth/presentation/request/LoginRequest.java b/admin/src/main/java/org/yapp/auth/presentation/request/LoginRequest.java new file mode 100644 index 0000000..ad8e82f --- /dev/null +++ b/admin/src/main/java/org/yapp/auth/presentation/request/LoginRequest.java @@ -0,0 +1,11 @@ +package org.yapp.auth.presentation.request; + +import jakarta.validation.constraints.NotNull; +import org.yapp.auth.application.dto.LoginDto; + +public record LoginRequest(@NotNull String loginId, @NotNull String password) { + + public LoginDto toDto() { + return new LoginDto(loginId, password); + } +} diff --git a/admin/src/main/resources/application.yml b/admin/src/main/resources/application.yml index 620ba3b..fb06f99 100644 --- a/admin/src/main/resources/application.yml +++ b/admin/src/main/resources/application.yml @@ -1,3 +1,3 @@ spring: profiles: - include: db \ No newline at end of file + include: db, secret \ No newline at end of file diff --git a/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java b/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java index 0b01dfb..3e90524 100644 --- a/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java +++ b/common/exception/src/main/java/org/yapp/error/code/auth/AuthErrorCode.java @@ -9,8 +9,10 @@ @RequiredArgsConstructor public enum AuthErrorCode implements ErrorCode { OAUTH_ERROR(HttpStatus.FORBIDDEN, "Oauth Error"), + ACCESS_DENIED(HttpStatus.FORBIDDEN, "권한이 없습니다."), ; + private final HttpStatus httpStatus; private final String message; } From d5decee6c141b3e3ae49083dfa305a8a57dd6b0a Mon Sep 17 00:00:00 2001 From: LujaeC Date: Thu, 23 Jan 2025 22:31:53 +0900 Subject: [PATCH 37/38] =?UTF-8?q?[PC-379]=20chore:=20=EB=88=84=EB=9D=BD=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- common/auth/build.gradle | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 common/auth/build.gradle diff --git a/common/auth/build.gradle b/common/auth/build.gradle new file mode 100644 index 0000000..fda8bf5 --- /dev/null +++ b/common/auth/build.gradle @@ -0,0 +1,19 @@ +plugins { + id 'java' +} + +group = 'org.yapp' +version = '0.0.1-SNAPSHOT' + +repositories { + mavenCentral() +} + +dependencies { + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} \ No newline at end of file From 7d2e9f3af2247fe85f396d89d0faaf04bf8ecb15 Mon Sep 17 00:00:00 2001 From: Chanho Lee Date: Sat, 25 Jan 2025 16:34:46 +0900 Subject: [PATCH 38/38] =?UTF-8?q?[PC-380]=20feat:=20=EB=A8=B8=EC=A7=80=20?= =?UTF-8?q?=EC=B6=A9=EB=8F=8C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/yapp/domain/match/MatchInfo.java | 64 +++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java b/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java index f3cb759..c3a4a33 100644 --- a/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java +++ b/common/domain/src/main/java/org/yapp/domain/match/MatchInfo.java @@ -15,30 +15,56 @@ @Getter public class MatchInfo { - @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; - @Column(name = "date") - private LocalDate date; + @Column(name = "date") + private LocalDate date; - @ManyToOne - @JoinColumn(name = "user_1") - private User user1; + @ManyToOne + @JoinColumn(name = "user_1") + private User user1; - @Column(name = "user_1_piece_checked") - private Boolean user1PieceChecked; + @Column(name = "user_1_piece_checked") + private Boolean user1PieceChecked = false; - @Column(name = "user_1_accept") - private Boolean user1Accepted; + @Column(name = "user_1_accept") + private Boolean user1Accepted = false; - @ManyToOne - @JoinColumn(name = "user_2") - private User user2; + @ManyToOne + @JoinColumn(name = "user_2") + private User user2; - @Column(name = "user_2_piece_checked") - private Boolean user2PieceChecked; + @Column(name = "user_2_piece_checked") + private Boolean user2PieceChecked = false; - @Column(name = "user_2_accept") - private Boolean user2Accepted; + @Column(name = "user_2_accept") + private Boolean user2Accepted = false; + + public MatchInfo(LocalDate date, User user1, User user2) { + this.date = date; + this.user1 = user1; + this.user2 = user2; + } + + public static MatchInfo createMatchInfo(User user1, User user2) { + return new MatchInfo(LocalDate.now(), user1, user2); + } + + public void checkPiece(Long userId) { + if (user1.getId().equals(userId)) { + user1PieceChecked = true; + } else { + user2PieceChecked = true; + } + } + + public void acceptPiece(Long userId) { + if (user1.getId().equals(userId)) { + user1Accepted = true; + } else { + user2Accepted = true; + } + } }