From 65afaf2a97602aafc07a4a7779debf0fe1dbdb8f Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 13 Jun 2025 20:05:19 +0900 Subject: [PATCH 001/123] =?UTF-8?q?feat=20:=20sql=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=20users,=20tasks,=20logs,=20commets=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onederful.sql | 65 +++++++++++++++++++++++ src/main/resources/application.properties | 3 -- 2 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 onederful.sql delete mode 100644 src/main/resources/application.properties diff --git a/onederful.sql b/onederful.sql new file mode 100644 index 0000000..36adcd8 --- /dev/null +++ b/onederful.sql @@ -0,0 +1,65 @@ +DROP DATABASE IF EXISTS onederful; +CREATE DATABASE IF NOT EXISTS onederful; +use onederful; + +CREATE TABLE users +( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '사용자 식별자', + email VARCHAR(100) NOT NULL UNIQUE COMMENT '이메일', + password VARCHAR(255) NOT NULL COMMENT '비밀번호', + name VARCHAR(100) NOT NULL COMMENT '이름', + role VARCHAR(50) NOT NULL COMMENT '권한 (ENUM)', + created_at DATETIME COMMENT '생성일자', + updated_at DATETIME COMMENT '수정일자', + deleted_at DATETIME COMMENT '삭제날짜', + is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부' +); + +CREATE TABLE tasks +( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '업무 식별자', + title VARCHAR(100) NOT NULL COMMENT '제목', + content TEXT NOT NULL COMMENT '설명', + priority VARCHAR(100) NOT NULL COMMENT '우선순위 식별자 (ENUM)', + manager_id BIGINT NOT NULL COMMENT '담당자 식별자 (FK)', + user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', + status VARCHAR(100) NOT NULL COMMENT '태스크 상태 (ENUM)', + due_at DATETIME COMMENT '마감일자', + started_at DATETIME COMMENT '시작일자', + created_at DATETIME COMMENT '생성일자', + updated_at DATETIME COMMENT '수정일자', + deleted_at DATETIME COMMENT '삭제날짜', + is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부', + + FOREIGN KEY (manager_id) REFERENCES users(id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); + +CREATE TABLE comments +( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '댓글 식별자', + content TEXT NOT NULL COMMENT '댓글 내용', + task_id BIGINT NOT NULL COMMENT '업무 식별자 (FK)', + user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', + created_at DATETIME COMMENT '생성일자', + updated_at DATETIME COMMENT '수정일자', + deleted_at DATETIME COMMENT '삭제날짜', + is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부', + + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, + FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE +); + +CREATE TABLE logs +( + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '로그 식별자', + user_id BIGINT NOT NULL COMMENT '사용자 식별자 (FK)', + activity VARCHAR(100) NOT NULL COMMENT '활동 유형', + ip_address VARCHAR(100) NOT NULL COMMENT 'ip 주소', + method_id BIGINT NOT NULL COMMENT '요청 메서드 (ENUM)', + target_id BIGINT NOT NULL COMMENT '작업 대상 식별자', + requestUrl VARCHAR(200) NOT NULL COMMENT '로그 요청 url', + created_at DATETIME COMMENT '생성일자', + + FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE +); diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties deleted file mode 100644 index fb897aa..0000000 --- a/src/main/resources/application.properties +++ /dev/null @@ -1,3 +0,0 @@ -spring: - application: - name: onederful \ No newline at end of file From cf52bddc7086feab08c08362e02c1a7748110103 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 13 Jun 2025 21:05:32 +0900 Subject: [PATCH 002/123] =?UTF-8?q?feat=20:=20sql=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onederful.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onederful.sql b/onederful.sql index 36adcd8..dd2498a 100644 --- a/onederful.sql +++ b/onederful.sql @@ -56,9 +56,9 @@ CREATE TABLE logs user_id BIGINT NOT NULL COMMENT '사용자 식별자 (FK)', activity VARCHAR(100) NOT NULL COMMENT '활동 유형', ip_address VARCHAR(100) NOT NULL COMMENT 'ip 주소', - method_id BIGINT NOT NULL COMMENT '요청 메서드 (ENUM)', + method VARCHAR(100) NOT NULL COMMENT '요청 메서드 (ENUM)', target_id BIGINT NOT NULL COMMENT '작업 대상 식별자', - requestUrl VARCHAR(200) NOT NULL COMMENT '로그 요청 url', + request_url VARCHAR(200) NOT NULL COMMENT '로그 요청 url', created_at DATETIME COMMENT '생성일자', FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE From 52bd028b5440bd0223a43c02fff193d2376cc84d Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 13 Jun 2025 21:06:24 +0900 Subject: [PATCH 003/123] =?UTF-8?q?feat=20:=20=EA=B8=B0=EB=B3=B8=EC=A0=81?= =?UTF-8?q?=EC=9D=B8=20Entity=20/=20=EA=B5=AC=EC=A1=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20=EA=B0=81=20=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=20?= =?UTF-8?q?=EB=A7=9E=EA=B2=8C=20=EC=97=94=ED=8B=B0=ED=8B=B0=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95,=20=EC=9D=BC=EB=B6=80=20ENUM=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/controller/.gitkeep | 0 .../onederful/domain/comment/dto/.gitkeep | 0 .../domain/comment/entity/Comment.java | 65 ++++++++++++++ .../domain/comment/repository/.gitkeep | 0 .../onederful/domain/comment/service/.gitkeep | 0 .../onederful/domain/log/controller/.gitkeep | 0 .../example/onederful/domain/log/dto/.gitkeep | 0 .../onederful/domain/log/entity/Log.java | 64 ++++++++++++++ .../onederful/domain/log/enums/Activity.java | 6 ++ .../onederful/domain/log/enums/Method.java | 5 ++ .../onederful/domain/log/repository/.gitkeep | 0 .../onederful/domain/log/service/.gitkeep | 0 .../onederful/domain/task/controller/.gitkeep | 0 .../onederful/domain/task/dto/.gitkeep | 0 .../onederful/domain/task/entity/Task.java | 84 +++++++++++++++++++ .../onederful/domain/task/enums/Priority.java | 5 ++ .../domain/task/enums/ProcessStatus.java | 5 ++ .../onederful/domain/task/repository/.gitkeep | 0 .../onederful/domain/task/service/.gitkeep | 0 .../onederful/domain/user/controller/.gitkeep | 0 .../onederful/domain/user/dto/.gitkeep | 0 .../onederful/domain/user/entity/User.java | 63 ++++++++++++++ .../onederful/domain/user/enums/Role.java | 5 ++ .../onederful/domain/user/repository/.gitkeep | 0 .../onederful/domain/user/service/.gitkeep | 0 25 files changed, 302 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/comment/controller/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/comment/entity/Comment.java create mode 100644 src/main/java/com/example/onederful/domain/comment/repository/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/comment/service/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/controller/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/dto/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/entity/Log.java create mode 100644 src/main/java/com/example/onederful/domain/log/enums/Activity.java create mode 100644 src/main/java/com/example/onederful/domain/log/enums/Method.java create mode 100644 src/main/java/com/example/onederful/domain/log/repository/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/service/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/task/controller/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/task/dto/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/task/entity/Task.java create mode 100644 src/main/java/com/example/onederful/domain/task/enums/Priority.java create mode 100644 src/main/java/com/example/onederful/domain/task/enums/ProcessStatus.java create mode 100644 src/main/java/com/example/onederful/domain/task/repository/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/task/service/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/user/controller/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/user/dto/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/user/entity/User.java create mode 100644 src/main/java/com/example/onederful/domain/user/enums/Role.java create mode 100644 src/main/java/com/example/onederful/domain/user/repository/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/user/service/.gitkeep diff --git a/src/main/java/com/example/onederful/domain/comment/controller/.gitkeep b/src/main/java/com/example/onederful/domain/comment/controller/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/comment/dto/.gitkeep b/src/main/java/com/example/onederful/domain/comment/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java new file mode 100644 index 0000000..3eb7610 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java @@ -0,0 +1,65 @@ +package com.example.onederful.domain.comment.entity; + +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.user.entity.User; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +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.OneToOne; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Entity +@Builder +@Getter +@Table(name = "comments") +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +public class Comment { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "content", nullable = false) + private String content; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name= "task_id", nullable = false) + private Task task; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name= "user_id", nullable = false) + private User user; + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @Builder.Default + @Column(name="is_deleted", nullable = false) + private Boolean isDeleted = false; + +} diff --git a/src/main/java/com/example/onederful/domain/comment/repository/.gitkeep b/src/main/java/com/example/onederful/domain/comment/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/comment/service/.gitkeep b/src/main/java/com/example/onederful/domain/comment/service/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/log/controller/.gitkeep b/src/main/java/com/example/onederful/domain/log/controller/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/log/dto/.gitkeep b/src/main/java/com/example/onederful/domain/log/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/log/entity/Log.java b/src/main/java/com/example/onederful/domain/log/entity/Log.java new file mode 100644 index 0000000..f01f6e1 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/entity/Log.java @@ -0,0 +1,64 @@ +package com.example.onederful.domain.log.entity; + +import com.example.onederful.domain.log.enums.Activity; +import com.example.onederful.domain.log.enums.Method; +import com.example.onederful.domain.user.entity.User; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +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 java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Entity +@Builder +@Getter +@Table(name = "logs") +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +public class Log { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="user_id", nullable = false) + private User user; + + @Enumerated(EnumType.STRING) + @Column(name="activity", nullable = false) + private Activity activity; + + @Column(name="ip_address", nullable=false) + private String ipAddress; + + @Enumerated(EnumType.STRING) + @Column(name = "method", nullable = false) + private Method method; + + @Column(name = "target_id", nullable = false) + private Long targetId; + + @Column(name="request_url", nullable = false) + private String requestUrl; + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; +} diff --git a/src/main/java/com/example/onederful/domain/log/enums/Activity.java b/src/main/java/com/example/onederful/domain/log/enums/Activity.java new file mode 100644 index 0000000..abd20e5 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/enums/Activity.java @@ -0,0 +1,6 @@ +package com.example.onederful.domain.log.enums; + +public enum Activity { +TASK_CREATED, TASK_UPDATED, TASK_DELETED,TASK_STATUS_CHANGED, COMMENT_CREATED +,COMMENT_UPDATED, COMMENT_DELETED, USER_LOGGED_IN, USER_LOGGED_OUT +} diff --git a/src/main/java/com/example/onederful/domain/log/enums/Method.java b/src/main/java/com/example/onederful/domain/log/enums/Method.java new file mode 100644 index 0000000..98a00ca --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/enums/Method.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.log.enums; + +public enum Method { + POST, GET, PATCH, PUT, DELETE +} diff --git a/src/main/java/com/example/onederful/domain/log/repository/.gitkeep b/src/main/java/com/example/onederful/domain/log/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/log/service/.gitkeep b/src/main/java/com/example/onederful/domain/log/service/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/task/controller/.gitkeep b/src/main/java/com/example/onederful/domain/task/controller/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/task/dto/.gitkeep b/src/main/java/com/example/onederful/domain/task/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/task/entity/Task.java b/src/main/java/com/example/onederful/domain/task/entity/Task.java new file mode 100644 index 0000000..539f035 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/entity/Task.java @@ -0,0 +1,84 @@ +package com.example.onederful.domain.task.entity; + + +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.user.entity.User; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +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 java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Entity +@Builder +@Getter +@Table(name = "tasks") +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +public class Task { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "title", nullable = false) + private String title; + + @Column(name = "content", nullable = false) + private String content; + + @Enumerated(EnumType.STRING) + @Column(name = "priority", nullable = false) + private Priority priority; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="manager_id", nullable = false) + private User manager; + + @ManyToOne(fetch = FetchType.LAZY) + @JoinColumn(name="user_id", nullable = false) + private User user; + + @Enumerated(EnumType.STRING) + @Column(name="status", nullable = false) + private ProcessStatus status; + + @Column(name="due_at", nullable = false) + private LocalDateTime dueAt; + + @Column(name="started_at", nullable=false) + private LocalDateTime startedAt; + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @Builder.Default + @Column(name="is_deleted", nullable = false) + private Boolean isDeleted = false; +} diff --git a/src/main/java/com/example/onederful/domain/task/enums/Priority.java b/src/main/java/com/example/onederful/domain/task/enums/Priority.java new file mode 100644 index 0000000..74f7633 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/enums/Priority.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.task.enums; + +public enum Priority { + LOW, MEDIUM, HIGH +} diff --git a/src/main/java/com/example/onederful/domain/task/enums/ProcessStatus.java b/src/main/java/com/example/onederful/domain/task/enums/ProcessStatus.java new file mode 100644 index 0000000..a828a6c --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/enums/ProcessStatus.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.task.enums; + +public enum ProcessStatus { + TODO,IN_PROGRESS,DONE +} diff --git a/src/main/java/com/example/onederful/domain/task/repository/.gitkeep b/src/main/java/com/example/onederful/domain/task/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/task/service/.gitkeep b/src/main/java/com/example/onederful/domain/task/service/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/user/controller/.gitkeep b/src/main/java/com/example/onederful/domain/user/controller/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/user/dto/.gitkeep b/src/main/java/com/example/onederful/domain/user/dto/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/user/entity/User.java b/src/main/java/com/example/onederful/domain/user/entity/User.java new file mode 100644 index 0000000..e49f7d0 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/entity/User.java @@ -0,0 +1,63 @@ +package com.example.onederful.domain.user.entity; + +import com.example.onederful.domain.user.enums.Role; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.EntityListeners; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import java.time.LocalDateTime; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; + +@Entity +@Builder +@Getter +@Table(name = "users") +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "email", nullable = false) + private String email; + + @Column(name="password", nullable = false) + private String password; + + @Column(name = "name", nullable = false) + private String name; + + @Enumerated(EnumType.STRING) + @Column(name= "role", nullable = false) + private Role role; + + @CreatedDate + @Column(name = "created_at", updatable = false) + private LocalDateTime createdAt; + + @LastModifiedDate + @Column(name = "updated_at") + private LocalDateTime updatedAt; + + @Column(name = "deleted_at") + private LocalDateTime deletedAt; + + @Builder.Default + @Column(name="is_deleted", nullable = false) + private Boolean isDeleted = false; +} diff --git a/src/main/java/com/example/onederful/domain/user/enums/Role.java b/src/main/java/com/example/onederful/domain/user/enums/Role.java new file mode 100644 index 0000000..b3cc86a --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/enums/Role.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.user.enums; + +public enum Role { + ADMIN, USER +} diff --git a/src/main/java/com/example/onederful/domain/user/repository/.gitkeep b/src/main/java/com/example/onederful/domain/user/repository/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/domain/user/service/.gitkeep b/src/main/java/com/example/onederful/domain/user/service/.gitkeep new file mode 100644 index 0000000..e69de29 From c75e365d527c84ed4a278995ee090fce04a1cd27 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 13 Jun 2025 21:06:37 +0900 Subject: [PATCH 004/123] =?UTF-8?q?feat=20:=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EA=B5=AC=EC=A1=B0=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/onederful/config/.gitkeep | 0 src/main/java/com/example/onederful/exception/.gitkeep | 0 src/main/java/com/example/onederful/filter/.gitkeep | 0 src/main/java/com/example/onederful/security/.gitkeep | 0 4 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/main/java/com/example/onederful/config/.gitkeep create mode 100644 src/main/java/com/example/onederful/exception/.gitkeep create mode 100644 src/main/java/com/example/onederful/filter/.gitkeep create mode 100644 src/main/java/com/example/onederful/security/.gitkeep diff --git a/src/main/java/com/example/onederful/config/.gitkeep b/src/main/java/com/example/onederful/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/exception/.gitkeep b/src/main/java/com/example/onederful/exception/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/filter/.gitkeep b/src/main/java/com/example/onederful/filter/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/src/main/java/com/example/onederful/security/.gitkeep b/src/main/java/com/example/onederful/security/.gitkeep new file mode 100644 index 0000000..e69de29 From 34e85ec95da764d2fe3c9c6d693a7d700ea50fd0 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Mon, 16 Jun 2025 09:32:04 +0900 Subject: [PATCH 005/123] =?UTF-8?q?feat=20:=20JpaAuditing=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 --- src/main/java/com/example/onederful/OnederfulApplication.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/com/example/onederful/OnederfulApplication.java b/src/main/java/com/example/onederful/OnederfulApplication.java index 19d88ac..ae0bc15 100644 --- a/src/main/java/com/example/onederful/OnederfulApplication.java +++ b/src/main/java/com/example/onederful/OnederfulApplication.java @@ -2,7 +2,9 @@ import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.data.jpa.repository.config.EnableJpaAuditing; +@EnableJpaAuditing @SpringBootApplication public class OnederfulApplication { From d2b58ad7023c2af014b516637bc43830c113e6cd Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 12:40:49 +0900 Subject: [PATCH 006/123] =?UTF-8?q?feat=20:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85,=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=EC=97=90=20=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20dto=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/dto/LoginRequestDto.java | 17 ++++++++++ .../domain/user/dto/LoginResponseDto.java | 11 +++++++ .../domain/user/dto/SignupRequestDto.java | 33 +++++++++++++++++++ .../domain/user/dto/SignupResponseDto.java | 11 +++++++ .../onederful/domain/user/dto/Tokeninfo.java | 5 +++ .../domain/user/dto/UserResponseDto.java | 13 ++++++++ 6 files changed, 90 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java create mode 100644 src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java create mode 100644 src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java create mode 100644 src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java create mode 100644 src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java create mode 100644 src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java diff --git a/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java new file mode 100644 index 0000000..a73f41f --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java @@ -0,0 +1,17 @@ +package com.example.onederful.domain.user.dto; + +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; + +public class LoginRequestDto { + + @NotBlank + private String username; + + @NotBlank + @Pattern( + regexp = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^\\w\\s]).+$", + message = "비밀번호는 대문자·소문자·숫자·특수문자를 각각 1자 이상 포함해야 합니다." + ) + private String password; +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java new file mode 100644 index 0000000..ca3f80c --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java @@ -0,0 +1,11 @@ +package com.example.onederful.domain.user.dto; + + +import java.time.OffsetDateTime; + +public class LoginResponseDto { + private boolean success; + private String message; + private Tokeninfo data; + private OffsetDateTime timestamp; +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java new file mode 100644 index 0000000..3f2efa0 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java @@ -0,0 +1,33 @@ +package com.example.onederful.domain.user.dto; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Getter +public class SignupRequestDto { + + @NotBlank + private String username; + + @NotBlank + @Email(message = "올바른 형식의 이메일 주소를 입력해주세요") + + @NotBlank + private String email; + + @NotBlank + @Pattern( + regexp = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^\\w\\s]).+$", + message = "비밀번호는 대문자·소문자·숫자·특수문자를 각각 1자 이상 포함해야 합니다." + ) + private String password; + + @NotBlank + private String name; +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java new file mode 100644 index 0000000..00ce3ef --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java @@ -0,0 +1,11 @@ +package com.example.onederful.domain.user.dto; + +import java.time.OffsetDateTime; + +public class SignupResponseDto { + private boolean success; + private String message; + private UserResponseDto data; + private OffsetDateTime timestamp; + +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java b/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java new file mode 100644 index 0000000..47320a7 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.user.dto; + +public class Tokeninfo { + private String token; +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java new file mode 100644 index 0000000..074bffc --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java @@ -0,0 +1,13 @@ +package com.example.onederful.domain.user.dto; + +import com.example.onederful.domain.user.enums.Role; + +import java.time.OffsetDateTime; + +public class UserResponseDto { + private String id; + private String username; + private String email; + private Role role; + private OffsetDateTime createdAt; +} From e41deead12c590de3424da2249ea61eb0d52831a Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 19:04:00 +0900 Subject: [PATCH 007/123] =?UTF-8?q?sql=20:=20=EA=B8=B0=EC=A1=B4=20users=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94=EC=97=90=EC=84=9C=20=EC=BB=AC?= =?UTF-8?q?=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 --- onederful.sql | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/onederful.sql b/onederful.sql index dd2498a..6ea1dfc 100644 --- a/onederful.sql +++ b/onederful.sql @@ -1,10 +1,7 @@ -DROP DATABASE IF EXISTS onederful; -CREATE DATABASE IF NOT EXISTS onederful; -use onederful; - CREATE TABLE users ( id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '사용자 식별자', + username VARCHAR(100) NOT NULL UNIQUE COMMENT '아이디', email VARCHAR(100) NOT NULL UNIQUE COMMENT '이메일', password VARCHAR(255) NOT NULL COMMENT '비밀번호', name VARCHAR(100) NOT NULL COMMENT '이름', From 46c174f95e6c480c6634195a7362cc2de25bec82 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 19:05:10 +0900 Subject: [PATCH 008/123] =?UTF-8?q?refactor=20:=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=ED=82=A4,=20=EB=A7=8C=EB=A3=8C=EC=8B=9C=EA=B0=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3c5778d..e8f7b4e 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -5,4 +5,10 @@ spring: datasource: url: ${DB_URL} username: ${DB_USERNAME} - password: ${DB_PASSWORD} \ No newline at end of file + password: ${DB_PASSWORD} + +jwt: + secret: + key: ${SECRET_KEY} + + expiration : 3600000 \ No newline at end of file From b94b3c7ec4c5de58878796e3faa5275b31e36aad Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 19:41:25 +0900 Subject: [PATCH 009/123] =?UTF-8?q?chore=20:=20=EB=B9=8C=EB=93=9C=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/build.gradle b/build.gradle index b8e8a1e..558b225 100644 --- a/build.gradle +++ b/build.gradle @@ -32,6 +32,14 @@ dependencies { annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // JWT + implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' + + // bcrypt + implementation 'at.favre.lib:bcrypt:0.10.2' } tasks.named('test') { From 5d77a1143c49faaedcce4aef43dbf1b2269c3077 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 19:59:39 +0900 Subject: [PATCH 010/123] =?UTF-8?q?feat=20:=20=ED=9A=8C=EC=9B=90=EA=B0=80?= =?UTF-8?q?=EC=9E=85,=20=EB=B9=84=EB=B0=80=EB=B2=88=ED=98=B8=20=EC=95=94?= =?UTF-8?q?=ED=98=B8=ED=99=94,=20Mapper=EC=9D=84=20=EC=9D=B4=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EC=97=AC=20ResponseBody=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=E2=86=92=20=EC=B6=94=ED=9B=84=20=EC=88=98=EC=A0=95=20=EC=98=88?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/config/PasswordEncoder.java | 17 +++++ .../domain/user/common/UserMapper.java | 75 +++++++++++++++++++ .../domain/user/dto/SignupRequestDto.java | 1 - .../domain/user/dto/SignupResponseDto.java | 6 ++ .../onederful/domain/user/entity/User.java | 7 ++ .../user/repository/UserRepository.java | 11 +++ .../domain/user/service/UserService.java | 64 ++++++++++++++++ 7 files changed, 180 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/onederful/config/PasswordEncoder.java create mode 100644 src/main/java/com/example/onederful/domain/user/common/UserMapper.java create mode 100644 src/main/java/com/example/onederful/domain/user/repository/UserRepository.java create mode 100644 src/main/java/com/example/onederful/domain/user/service/UserService.java diff --git a/src/main/java/com/example/onederful/config/PasswordEncoder.java b/src/main/java/com/example/onederful/config/PasswordEncoder.java new file mode 100644 index 0000000..f86d150 --- /dev/null +++ b/src/main/java/com/example/onederful/config/PasswordEncoder.java @@ -0,0 +1,17 @@ +package com.example.onederful.config; + +import at.favre.lib.crypto.bcrypt.BCrypt; +import org.springframework.stereotype.Component; + +@Component +public class PasswordEncoder { + + public String encode(String rawPassword){ + return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST,rawPassword.toCharArray()); + } + + public boolean matches(String rawPassword, String encodedPassword){ + BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(),encodedPassword); + return result.verified; + } +} diff --git a/src/main/java/com/example/onederful/domain/user/common/UserMapper.java b/src/main/java/com/example/onederful/domain/user/common/UserMapper.java new file mode 100644 index 0000000..f0a4186 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/common/UserMapper.java @@ -0,0 +1,75 @@ +package com.example.onederful.domain.user.common; + + +import com.example.onederful.domain.user.dto.*; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.enums.Role; + +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import java.util.Date; + +public class UserMapper { + + public static User user (SignupRequestDto dto){ + return User.builder() + .username(dto.getUsername()) + .email(dto.getEmail()) + .password(dto.getPassword()) + .name(dto.getName()) + .role(Role.USER) + .isDeleted(false) + .build(); + } + + // ResponseBody에서 data + public static UserResponseDto userResponseDto (User user){ + // LocalDateTime -> OffsetDateTime + OffsetDateTime createAt = user.getCreatedAt().atOffset(ZoneOffset.UTC); + + return new UserResponseDto( + user.getId(), + user.getUsername(), + user.getEmail(), + user.getName(), + user.getRole(), + createAt + ); + } + + // 회원가입 ResponseBody + public static SignupResponseDto signupResponseDto(UserResponseDto data){ + Date date = new Date(); + OffsetDateTime timestamp = date.toInstant().atOffset(ZoneOffset.UTC); + + return new SignupResponseDto( + true, + "회원가입이 성공하였습니다", + data, + timestamp + ); + } + + // 토큰 담기 + public static Tokeninfo token (String token){ + + String newToken = token.substring(7); + + return new Tokeninfo(newToken); + } + + public static LoginResponseDto LoginResponseDto (Tokeninfo data){ + + Date date = new Date(); + OffsetDateTime timestamp = date.toInstant().atOffset(ZoneOffset.UTC); + + return new LoginResponseDto( + true, + "로그인이 완료되었습니다.", + data, + timestamp + ); + + } + +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java index 3f2efa0..df5b31b 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java @@ -17,7 +17,6 @@ public class SignupRequestDto { @NotBlank @Email(message = "올바른 형식의 이메일 주소를 입력해주세요") - @NotBlank private String email; diff --git a/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java index 00ce3ef..7906290 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java @@ -1,7 +1,13 @@ package com.example.onederful.domain.user.dto; +import lombok.AllArgsConstructor; +import lombok.Getter; + + import java.time.OffsetDateTime; +@Getter +@AllArgsConstructor public class SignupResponseDto { private boolean success; private String message; diff --git a/src/main/java/com/example/onederful/domain/user/entity/User.java b/src/main/java/com/example/onederful/domain/user/entity/User.java index e49f7d0..647089c 100644 --- a/src/main/java/com/example/onederful/domain/user/entity/User.java +++ b/src/main/java/com/example/onederful/domain/user/entity/User.java @@ -33,6 +33,9 @@ public class User { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(name = "username", nullable = false) + private String username; + @Column(name = "email", nullable = false) private String email; @@ -60,4 +63,8 @@ public class User { @Builder.Default @Column(name="is_deleted", nullable = false) private Boolean isDeleted = false; + + public void setEncodedPassword(String Password){ + this.password = Password; + } } diff --git a/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java b/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java new file mode 100644 index 0000000..731b95d --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java @@ -0,0 +1,11 @@ +package com.example.onederful.domain.user.repository; + +import com.example.onederful.domain.user.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface UserRepository extends JpaRepository { + Optional findByEmail(String email); + Optional findByUsername(String username); +} diff --git a/src/main/java/com/example/onederful/domain/user/service/UserService.java b/src/main/java/com/example/onederful/domain/user/service/UserService.java new file mode 100644 index 0000000..5526834 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/service/UserService.java @@ -0,0 +1,64 @@ +package com.example.onederful.domain.user.service; + +import com.example.onederful.config.PasswordEncoder; +import com.example.onederful.domain.user.common.UserMapper; +import com.example.onederful.domain.user.dto.*; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.security.JwtUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class UserService { + + private final PasswordEncoder passwordEncoder; + private final UserRepository userRepository; + private final JwtUtil jwtUtil; + + // 회원가입 + public SignupResponseDto signup(SignupRequestDto dto){ + + // 이메일 중복 확인 + userRepository.findByEmail(dto.getEmail()).ifPresent( + user -> {throw new IllegalArgumentException("등록된 이메일이 존재합니다.");} + ); + + // Dto → Entity + User user = UserMapper.user(dto); + + // 비밀번호 암호화 + user.setEncodedPassword(passwordEncoder.encode(user.getPassword())); + + User savedUser = userRepository.save(user); + + // data + UserResponseDto userResponseDto = UserMapper.userResponseDto(savedUser); + + return UserMapper.signupResponseDto(userResponseDto); + } + + + // 로그인 + public LoginResponseDto login(LoginRequestDto dto){ + String username = dto.getUsername(); + String password = dto.getPassword(); + + User user = userRepository.findByUsername(username).orElseThrow( + () -> new IllegalArgumentException("아이디가 일치하지 않습니다.") + ); + + if(!passwordEncoder.matches(password,user.getPassword())){ + throw new IllegalArgumentException("비밀번호가 일치하지 않습니다"); + } + + // JWT Token + String token = jwtUtil.generateToken(user); + + // data + Tokeninfo data = UserMapper.token(token); + + return UserMapper.LoginResponseDto(data); + } +} From ab9c690d2915e97942a35319882bf276e550a79b Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 20:00:54 +0900 Subject: [PATCH 011/123] =?UTF-8?q?feat=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8,?= =?UTF-8?q?=20JWT=20=ED=86=A0=ED=81=B0=20=EC=83=9D=EC=84=B1,=20=ED=95=84?= =?UTF-8?q?=ED=84=B0=20=EC=B2=98=EB=A6=AC=20(=EC=83=9D=EC=84=B1,=20?= =?UTF-8?q?=EA=B2=80=EC=A6=9D)=EB=A7=8C=20=EB=A7=8C=EB=93=A4=EC=97=88?= =?UTF-8?q?=EC=8A=B5=EB=8B=88=EB=8B=A4.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/AuthController.java | 41 +++++++ .../domain/user/dto/LoginRequestDto.java | 6 + .../domain/user/dto/LoginResponseDto.java | 6 + .../onederful/domain/user/dto/Tokeninfo.java | 5 + .../domain/user/dto/UserResponseDto.java | 8 +- .../example/onederful/filter/JwtFilter.java | 58 ++++++++++ .../example/onederful/security/JwtUtil.java | 103 ++++++++++++++++++ 7 files changed, 226 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/example/onederful/domain/user/controller/AuthController.java create mode 100644 src/main/java/com/example/onederful/filter/JwtFilter.java create mode 100644 src/main/java/com/example/onederful/security/JwtUtil.java diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java new file mode 100644 index 0000000..d0461a5 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -0,0 +1,41 @@ +package com.example.onederful.domain.user.controller; + +import com.example.onederful.domain.user.dto.*; +import com.example.onederful.domain.user.service.UserService; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequiredArgsConstructor +@RequestMapping("/api") +public class AuthController { + + private final UserService userService; + + // 회원가입 + @PostMapping("/auth/register") + public ResponseEntity register(@RequestBody SignupRequestDto requestDto){ + SignupResponseDto signup = userService.signup(requestDto); + return ResponseEntity.ok(signup); + } + + // 로그인 + @PostMapping("/auth/login") + public ResponseEntity login(@RequestBody LoginRequestDto requestDto){ + LoginResponseDto login = userService.login(requestDto); + + return ResponseEntity.ok(login); + } + + // 현재 사용자 정보 조회 +// @GetMapping("/users/me") +// public ResponseEntity select (HttpServletRequest request){ +// +// } + + +} diff --git a/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java index a73f41f..0181cb5 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java @@ -2,7 +2,13 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +@NoArgsConstructor +@AllArgsConstructor +@Getter public class LoginRequestDto { @NotBlank diff --git a/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java index ca3f80c..fff5346 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java @@ -1,8 +1,14 @@ package com.example.onederful.domain.user.dto; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; import java.time.OffsetDateTime; +@AllArgsConstructor +@NoArgsConstructor +@Getter public class LoginResponseDto { private boolean success; private String message; diff --git a/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java b/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java index 47320a7..d5da589 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java +++ b/src/main/java/com/example/onederful/domain/user/dto/Tokeninfo.java @@ -1,5 +1,10 @@ package com.example.onederful.domain.user.dto; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor public class Tokeninfo { private String token; } diff --git a/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java index 074bffc..e027bd2 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/UserResponseDto.java @@ -1,13 +1,19 @@ package com.example.onederful.domain.user.dto; import com.example.onederful.domain.user.enums.Role; +import lombok.AllArgsConstructor; +import lombok.Getter; + import java.time.OffsetDateTime; +@Getter +@AllArgsConstructor public class UserResponseDto { - private String id; + private Long id; private String username; private String email; + private String name; private Role role; private OffsetDateTime createdAt; } diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java new file mode 100644 index 0000000..18ff4c6 --- /dev/null +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -0,0 +1,58 @@ +package com.example.onederful.filter; + +import com.example.onederful.security.JwtUtil; +import jakarta.servlet.*; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; + +@Slf4j +@RequiredArgsConstructor +public class JwtFilter implements Filter { + + private final JwtUtil jwtUtil; + + @Override + public void doFilter( + ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) throws IOException, ServletException { + + HttpServletRequest request = (HttpServletRequest) servletRequest; + HttpServletResponse response = (HttpServletResponse) servletResponse; + + String requestURI = request.getRequestURI(); + + String authorizationHeader = request.getHeader("Authorization"); + + + // 회원가입, 로그인 경우 + if(requestURI.startsWith("/api/auth/register") || requestURI.startsWith("/api/auth/login")){ + filterChain.doFilter(servletRequest, servletResponse); + return; + } + + // 토큰 존재 유무 확인 + if(authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")){ + log.info("JWT 토큰이 필요합니다."); + response.sendError(response.SC_UNAUTHORIZED,"JWT 토큰이 필요합니다."); + return; + } + + // "Bearer" 빼고 확인 + String jwt = authorizationHeader.substring(7); + + // 토큰 검증 유무 확인 + if(!jwtUtil.validateToken(jwt)){ + response.setStatus(HttpServletResponse.SC_FORBIDDEN); + response.getWriter().write("{\"error\": \"Unauthorized\"}"); + } + + filterChain.doFilter(servletRequest,servletResponse); + + + } +} diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java new file mode 100644 index 0000000..6b59fd3 --- /dev/null +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -0,0 +1,103 @@ +package com.example.onederful.security; + +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.enums.Role; +import io.jsonwebtoken.*; +import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SecurityException; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.security.Key; +import java.util.Base64; +import java.util.Date; + +@Slf4j +@Component +public class JwtUtil { + + // JWT Token 접두사 + public final static String BEARER_PREFIX = "Bearer "; + + // JWT Token 만료시간 + @Value("${jwt.expiration}") + public Long expirationTime; + + // JWT 서명 알고리즘 + private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; + + // 비밀 키 + @Value("${jwt.secret.key}") + private String secretKey; + + // 실제 서명에서 사용할 키 객체 + private Key key; + + + /** + * 빈 초기화 메서드 + * - 애플리케이션 실행 시 비밀키를 Base64로 디코딩 하여 key 객체를 초기화 + */ + @PostConstruct + public void init(){ + byte [] bytes = Base64.getDecoder().decode(secretKey); + key = Keys.hmacShaKeyFor(bytes); + } + + + /** + * JWT 토큰 생성 + * @param user User Entity + * @return 생성된 JWT 토큰 + */ + public String generateToken(User user){ + + String username = user.getUsername(); + String email = user.getEmail(); + String name = user.getName(); + Role role = user.getRole(); + Date date = new Date(); + + return BEARER_PREFIX + + Jwts.builder() + .setSubject(username) + .claim("role", role) + .claim("email", email) + .claim("name", name) + .setIssuedAt(date) + .setExpiration(new Date(date.getTime()+ expirationTime)) + .signWith(key,signatureAlgorithm) + .compact(); + } + + + /** + * JWT 토큰 유효성 검증 + * @param token JWT 토큰 + * @return 토큰의 유효성 여부 (true : 유효, false : 유효하지 않음) + */ + public boolean validateToken(String token){ + try { + Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token); + return true; + }catch (SecurityException | MalformedJwtException e){ + log.error("Invalid JWT signature, 유효하지 않은 JWT 서명입니다."); + }catch (ExpiredJwtException e){ + log.error("Expired JWT token, 만료된 JWT token 입니다.", e); + }catch (UnsupportedJwtException e){ + log.error("Unsupported JWT token, 지원되지 않는 JWT 토큰 입니다.", e); + }catch (IllegalArgumentException e){ + log.error("JWT claims is empty, 잘못된 JWT 토큰 입니다.", e); + } + return false; + } + + + + +} From 87c80101fd7c76359f4ae04276e85bcf8b85b22c Mon Sep 17 00:00:00 2001 From: DongGeun Date: Mon, 16 Jun 2025 20:02:55 +0900 Subject: [PATCH 012/123] =?UTF-8?q?chore=20:=20=EB=B9=8C=EB=93=9C=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build.gradle b/build.gradle index 558b225..22f4c2e 100644 --- a/build.gradle +++ b/build.gradle @@ -40,6 +40,9 @@ dependencies { // bcrypt implementation 'at.favre.lib:bcrypt:0.10.2' + + // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' } tasks.named('test') { From c2351d1f9287da6e4bbd48ebc72bc7e443c9480c Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:24:13 +0900 Subject: [PATCH 013/123] =?UTF-8?q?remove=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20DTO=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/dto/LoginRequestDto.java | 23 ------------------- .../domain/user/dto/LoginResponseDto.java | 17 -------------- 2 files changed, 40 deletions(-) delete mode 100644 src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java delete mode 100644 src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java diff --git a/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java deleted file mode 100644 index 0181cb5..0000000 --- a/src/main/java/com/example/onederful/domain/user/dto/LoginRequestDto.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.example.onederful.domain.user.dto; - -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.Pattern; -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -@NoArgsConstructor -@AllArgsConstructor -@Getter -public class LoginRequestDto { - - @NotBlank - private String username; - - @NotBlank - @Pattern( - regexp = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^\\w\\s]).+$", - message = "비밀번호는 대문자·소문자·숫자·특수문자를 각각 1자 이상 포함해야 합니다." - ) - private String password; -} diff --git a/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java deleted file mode 100644 index fff5346..0000000 --- a/src/main/java/com/example/onederful/domain/user/dto/LoginResponseDto.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.onederful.domain.user.dto; - -import lombok.AllArgsConstructor; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.OffsetDateTime; - -@AllArgsConstructor -@NoArgsConstructor -@Getter -public class LoginResponseDto { - private boolean success; - private String message; - private Tokeninfo data; - private OffsetDateTime timestamp; -} From 2cdd0773495d3699d3a81fddf651ab11f22b8d93 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:27:06 +0900 Subject: [PATCH 014/123] =?UTF-8?q?feat=20:=20JwtUtil=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EB=A1=9C=EB=93=9C=EC=97=90=EC=84=9C=20Id=20=EA=B0=92=20?= =?UTF-8?q?=EC=B6=94=EC=B6=9C=20=EB=A9=94=EC=84=9C=EB=93=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1,=20JwtFilter=20return=20=EC=B6=94=EA=B0=80,=20WebConf?= =?UTF-8?q?ig=20JwtFilter=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/config/WebConfig.java | 22 +++++++++++++ .../example/onederful/filter/JwtFilter.java | 5 ++- .../example/onederful/security/JwtUtil.java | 32 +++++++++++++++---- 3 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 src/main/java/com/example/onederful/config/WebConfig.java diff --git a/src/main/java/com/example/onederful/config/WebConfig.java b/src/main/java/com/example/onederful/config/WebConfig.java new file mode 100644 index 0000000..90fc4fa --- /dev/null +++ b/src/main/java/com/example/onederful/config/WebConfig.java @@ -0,0 +1,22 @@ +package com.example.onederful.config; + +import com.example.onederful.filter.JwtFilter; +import com.example.onederful.security.JwtUtil; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class WebConfig { + + @Bean + public FilterRegistrationBean jwtFilter(JwtUtil jwtUtil){ + FilterRegistrationBean registrationBean = new FilterRegistrationBean<>(); + + registrationBean.setFilter(new JwtFilter(jwtUtil)); + registrationBean.setOrder(1); + registrationBean.addUrlPatterns("/*"); + + return registrationBean; + } +} diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java index 18ff4c6..28453ae 100644 --- a/src/main/java/com/example/onederful/filter/JwtFilter.java +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -41,7 +41,7 @@ public void doFilter( response.sendError(response.SC_UNAUTHORIZED,"JWT 토큰이 필요합니다."); return; } - + // "Bearer" 빼고 확인 String jwt = authorizationHeader.substring(7); @@ -49,10 +49,9 @@ public void doFilter( if(!jwtUtil.validateToken(jwt)){ response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("{\"error\": \"Unauthorized\"}"); + return; } filterChain.doFilter(servletRequest,servletResponse); - - } } diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java index 6b59fd3..fb6c45b 100644 --- a/src/main/java/com/example/onederful/security/JwtUtil.java +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -54,18 +54,14 @@ public void init(){ */ public String generateToken(User user){ + Long id = user.getId(); String username = user.getUsername(); - String email = user.getEmail(); - String name = user.getName(); - Role role = user.getRole(); Date date = new Date(); return BEARER_PREFIX + Jwts.builder() .setSubject(username) - .claim("role", role) - .claim("email", email) - .claim("name", name) + .claim("id",id) .setIssuedAt(date) .setExpiration(new Date(date.getTime()+ expirationTime)) .signWith(key,signatureAlgorithm) @@ -97,7 +93,29 @@ public boolean validateToken(String token){ return false; } - + /** + * Token에 존재하는 모든 클레임(페이로드 값)을 추출 + * @param token 검증된 JWT 토큰 (로그인 한 상태) + * @return 클라임 객체 + */ + public Claims extractAllClaims(String token){ + return Jwts.parserBuilder() + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); + } + + /** + * Token에 저장된 ID(기본키) 가져오기 + * @param token + * @return + */ + public Long extractId(String token){ + return extractAllClaims(token).get("id",Long.class); + } + + } From 7a134081ca90e476cf10871e25e9f79922b92ebc Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:28:59 +0900 Subject: [PATCH 015/123] =?UTF-8?q?comment=20:=20=EC=A3=BC=EC=84=9D=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EB=B0=8F=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20import=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/onederful/security/JwtUtil.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java index fb6c45b..6b73706 100644 --- a/src/main/java/com/example/onederful/security/JwtUtil.java +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -1,7 +1,6 @@ package com.example.onederful.security; import com.example.onederful.domain.user.entity.User; -import com.example.onederful.domain.user.enums.Role; import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SecurityException; @@ -108,8 +107,8 @@ public Claims extractAllClaims(String token){ /** * Token에 저장된 ID(기본키) 가져오기 - * @param token - * @return + * @param token 검증된 JWT 토큰 (로그인 한 상태) + * @return ID값 */ public Long extractId(String token){ return extractAllClaims(token).get("id",Long.class); From b3c91336e735ebb15f1f6d1250a308aeb7a60b72 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:30:37 +0900 Subject: [PATCH 016/123] =?UTF-8?q?feat=20:=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=83=9D=EC=84=B1=20,?= =?UTF-8?q?=20enum=20=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=BD=94=EB=93=9C=20=EC=A0=95=EB=A6=AC,?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/exception/CustomException.java | 11 ++++++++ .../onederful/exception/ErrorCode.java | 18 +++++++++++++ .../exception/GlobalExceptionHandler.java | 26 +++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 src/main/java/com/example/onederful/exception/CustomException.java create mode 100644 src/main/java/com/example/onederful/exception/ErrorCode.java create mode 100644 src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java diff --git a/src/main/java/com/example/onederful/exception/CustomException.java b/src/main/java/com/example/onederful/exception/CustomException.java new file mode 100644 index 0000000..97a182f --- /dev/null +++ b/src/main/java/com/example/onederful/exception/CustomException.java @@ -0,0 +1,11 @@ +package com.example.onederful.exception; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public class CustomException extends RuntimeException{ + private final ErrorCode errorCode; + +} diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java new file mode 100644 index 0000000..e263aac --- /dev/null +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -0,0 +1,18 @@ +package com.example.onederful.exception; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import org.springframework.http.HttpStatus; + +@AllArgsConstructor +@Getter +public enum ErrorCode { + DUPLICATE_USER(HttpStatus.CONFLICT,"이미 존재하는 사용자입니다."), + BAD_REQUEST(HttpStatus.BAD_REQUEST,"잘못된 사용자명 또는 비밀번호입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"인증이 필요합니다."), + INVALID_PASSWORD(HttpStatus.UNAUTHORIZED,"비밀번호가 일치하지 않습니다."), + LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."); + + private final HttpStatus status; + private final String message; +} diff --git a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..8b931af --- /dev/null +++ b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java @@ -0,0 +1,26 @@ +package com.example.onederful.exception; + +import com.example.onederful.domain.user.dto.ApiResponseDto; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; + +import java.time.OffsetDateTime; + +@ControllerAdvice +public class GlobalExceptionHandler { + + @ExceptionHandler(CustomException.class) + public ResponseEntity handleCustomException(CustomException e){ + ErrorCode errorCode = e.getErrorCode(); + + ApiResponseDto response = new ApiResponseDto( + false, + errorCode.getMessage(), + null, + OffsetDateTime.now() + ); + + return ResponseEntity.status(errorCode.getStatus()).body(response); + } +} From 55beabe8c5d1fd63e24ab3660efa68b135c81ec5 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:30:59 +0900 Subject: [PATCH 017/123] =?UTF-8?q?feat=20:=20groups=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=EC=9D=84=20=EC=82=AC=EC=9A=A9=ED=95=98=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=20LoginGroup,=20SignupGroup=20=EC=9D=B8=ED=84=B0?= =?UTF-8?q?=ED=8E=98=EC=9D=B4=EC=8A=A4=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/onederful/domain/user/common/LoginGroup.java | 4 ++++ .../com/example/onederful/domain/user/common/SignupGroup.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/user/common/LoginGroup.java create mode 100644 src/main/java/com/example/onederful/domain/user/common/SignupGroup.java diff --git a/src/main/java/com/example/onederful/domain/user/common/LoginGroup.java b/src/main/java/com/example/onederful/domain/user/common/LoginGroup.java new file mode 100644 index 0000000..9a2a32d --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/common/LoginGroup.java @@ -0,0 +1,4 @@ +package com.example.onederful.domain.user.common; + +public interface LoginGroup { +} diff --git a/src/main/java/com/example/onederful/domain/user/common/SignupGroup.java b/src/main/java/com/example/onederful/domain/user/common/SignupGroup.java new file mode 100644 index 0000000..0e42206 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/common/SignupGroup.java @@ -0,0 +1,4 @@ +package com.example.onederful.domain.user.common; + +public interface SignupGroup { +} From 1629040f93cfcca4d0c0681e64b14397f8517411 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:31:47 +0900 Subject: [PATCH 018/123] =?UTF-8?q?feat=20:=20LoginRequestDto,=20SignupReq?= =?UTF-8?q?uestDto=20=ED=86=B5=ED=95=A9=ED=95=98=EA=B8=B0=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=20groups=20=EA=B8=B0=EB=8A=A5=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{SignupRequestDto.java => RequestDto.java} | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) rename src/main/java/com/example/onederful/domain/user/dto/{SignupRequestDto.java => RequestDto.java} (54%) diff --git a/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java similarity index 54% rename from src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java rename to src/main/java/com/example/onederful/domain/user/dto/RequestDto.java index df5b31b..457dbcb 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/SignupRequestDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java @@ -1,5 +1,7 @@ package com.example.onederful.domain.user.dto; +import com.example.onederful.domain.user.common.LoginGroup; +import com.example.onederful.domain.user.common.SignupGroup; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; @@ -10,23 +12,23 @@ @AllArgsConstructor @NoArgsConstructor @Getter -public class SignupRequestDto { +public class RequestDto { - @NotBlank + @NotBlank(groups = {SignupGroup.class, LoginGroup.class}) private String username; - @NotBlank - @Email(message = "올바른 형식의 이메일 주소를 입력해주세요") - @NotBlank + @NotBlank (groups = {SignupGroup.class}) + @Email (groups = {SignupGroup.class}, message = "올바른 형식의 이메일 주소를 입력해주세요") private String email; - @NotBlank - @Pattern( + @NotBlank (groups = {SignupGroup.class,LoginGroup.class}) + @Pattern (groups = {SignupGroup.class,LoginGroup.class}, regexp = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^\\w\\s]).+$", message = "비밀번호는 대문자·소문자·숫자·특수문자를 각각 1자 이상 포함해야 합니다." ) private String password; - @NotBlank + @NotBlank (groups = {SignupGroup.class}) private String name; + } From 264ed27e040dbce4bd43bdb3eb603412852ac773 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:33:57 +0900 Subject: [PATCH 019/123] =?UTF-8?q?feat=20:=20ApiResponseDto=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=EC=9D=91=EB=8B=B5=20DTO=20=EC=83=9D=EC=84=B1,=20Us?= =?UTF-8?q?erMapper=20=EC=9D=91=EB=8B=B5=20=EC=84=B1=EA=B3=B5=20=EC=8B=9C?= =?UTF-8?q?=20=EB=B0=98=ED=99=98=EA=B0=92=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/common/UserMapper.java | 55 +++++++++++-------- ...upResponseDto.java => ApiResponseDto.java} | 7 +-- 2 files changed, 36 insertions(+), 26 deletions(-) rename src/main/java/com/example/onederful/domain/user/dto/{SignupResponseDto.java => ApiResponseDto.java} (79%) diff --git a/src/main/java/com/example/onederful/domain/user/common/UserMapper.java b/src/main/java/com/example/onederful/domain/user/common/UserMapper.java index f0a4186..21017f3 100644 --- a/src/main/java/com/example/onederful/domain/user/common/UserMapper.java +++ b/src/main/java/com/example/onederful/domain/user/common/UserMapper.java @@ -11,7 +11,7 @@ public class UserMapper { - public static User user (SignupRequestDto dto){ + public static User user (RequestDto dto){ return User.builder() .username(dto.getUsername()) .email(dto.getEmail()) @@ -22,8 +22,8 @@ public static User user (SignupRequestDto dto){ .build(); } - // ResponseBody에서 data - public static UserResponseDto userResponseDto (User user){ + // ResponseBody data (유저 정보) + public static UserResponseDto data(User user){ // LocalDateTime -> OffsetDateTime OffsetDateTime createAt = user.getCreatedAt().atOffset(ZoneOffset.UTC); @@ -37,39 +37,50 @@ public static UserResponseDto userResponseDto (User user){ ); } - // 회원가입 ResponseBody - public static SignupResponseDto signupResponseDto(UserResponseDto data){ - Date date = new Date(); - OffsetDateTime timestamp = date.toInstant().atOffset(ZoneOffset.UTC); - - return new SignupResponseDto( - true, - "회원가입이 성공하였습니다", - data, - timestamp - ); - } - - // 토큰 담기 + // ResponseBody date (Token) public static Tokeninfo token (String token){ String newToken = token.substring(7); return new Tokeninfo(newToken); } - - public static LoginResponseDto LoginResponseDto (Tokeninfo data){ + // ResponseBody createdAt + public static OffsetDateTime currentTime(){ Date date = new Date(); - OffsetDateTime timestamp = date.toInstant().atOffset(ZoneOffset.UTC); + return date.toInstant().atOffset(ZoneOffset.UTC); + } + + // 회원가입 ResponseBody + public static ApiResponseDto signupResponse(UserResponseDto data){ + + return new ApiResponseDto( + true, + "회원가입이 성공하였습니다", + data, + currentTime() + ); + } + + // 로그인 ResponseBody + public static ApiResponseDto LoginResponse (Tokeninfo data){ - return new LoginResponseDto( + return new ApiResponseDto( true, "로그인이 완료되었습니다.", data, - timestamp + currentTime() ); + } + // 회원 정보 조회 + public static ApiResponseDto selectResponse(UserResponseDto data){ + return new ApiResponseDto( + true, + "사용자가 정보를 조회했습니다.", + data, + currentTime() + ); } } diff --git a/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java similarity index 79% rename from src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java rename to src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java index 7906290..516bac9 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/SignupResponseDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java @@ -3,15 +3,14 @@ import lombok.AllArgsConstructor; import lombok.Getter; - import java.time.OffsetDateTime; @Getter @AllArgsConstructor -public class SignupResponseDto { +public class ApiResponseDto { + private boolean success; private String message; - private UserResponseDto data; + private Object data; private OffsetDateTime timestamp; - } From 4b1e85b4df05bdcc10d90f4c6a2a86157f5db695 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 02:36:22 +0900 Subject: [PATCH 020/123] =?UTF-8?q?feat=20:=20AuthController=20=ED=9A=8C?= =?UTF-8?q?=EC=9B=90=20=EC=A0=95=EB=B3=B4=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80,=20UserService=20=ED=9A=8C=EC=9B=90=EC=A0=95=EB=B3=B4?= =?UTF-8?q?=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/AuthController.java | 32 ++++++++------ .../domain/user/service/UserService.java | 43 ++++++++++++++----- 2 files changed, 53 insertions(+), 22 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java index d0461a5..346040f 100644 --- a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -1,14 +1,16 @@ package com.example.onederful.domain.user.controller; +import com.example.onederful.domain.user.common.LoginGroup; +import com.example.onederful.domain.user.common.SignupGroup; import com.example.onederful.domain.user.dto.*; import com.example.onederful.domain.user.service.UserService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.List; - @RestController @RequiredArgsConstructor @RequestMapping("/api") @@ -18,24 +20,30 @@ public class AuthController { // 회원가입 @PostMapping("/auth/register") - public ResponseEntity register(@RequestBody SignupRequestDto requestDto){ - SignupResponseDto signup = userService.signup(requestDto); - return ResponseEntity.ok(signup); + public ResponseEntity register(@Validated(SignupGroup.class) @RequestBody RequestDto requestDto){ + + ApiResponseDto signup = userService.signup(requestDto); + + return ResponseEntity.status(HttpStatus.OK).body(signup); } // 로그인 @PostMapping("/auth/login") - public ResponseEntity login(@RequestBody LoginRequestDto requestDto){ - LoginResponseDto login = userService.login(requestDto); + public ResponseEntity login(@Validated(LoginGroup.class) @RequestBody RequestDto requestDto){ + + ApiResponseDto login = userService.login(requestDto); - return ResponseEntity.ok(login); + return ResponseEntity.status(HttpStatus.OK).body(login); } // 현재 사용자 정보 조회 -// @GetMapping("/users/me") -// public ResponseEntity select (HttpServletRequest request){ -// -// } + @GetMapping("/users/me") + public ResponseEntity select (HttpServletRequest request){ + + ApiResponseDto select = userService.select(request); + + return ResponseEntity.status(HttpStatus.OK).body(select); + } } diff --git a/src/main/java/com/example/onederful/domain/user/service/UserService.java b/src/main/java/com/example/onederful/domain/user/service/UserService.java index 5526834..e3dce19 100644 --- a/src/main/java/com/example/onederful/domain/user/service/UserService.java +++ b/src/main/java/com/example/onederful/domain/user/service/UserService.java @@ -5,7 +5,10 @@ import com.example.onederful.domain.user.dto.*; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.exception.CustomException; +import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -18,11 +21,11 @@ public class UserService { private final JwtUtil jwtUtil; // 회원가입 - public SignupResponseDto signup(SignupRequestDto dto){ + public ApiResponseDto signup(RequestDto dto){ // 이메일 중복 확인 userRepository.findByEmail(dto.getEmail()).ifPresent( - user -> {throw new IllegalArgumentException("등록된 이메일이 존재합니다.");} + user -> {throw new CustomException(ErrorCode.DUPLICATE_USER);} ); // Dto → Entity @@ -33,32 +36,52 @@ public SignupResponseDto signup(SignupRequestDto dto){ User savedUser = userRepository.save(user); - // data - UserResponseDto userResponseDto = UserMapper.userResponseDto(savedUser); + // ResponseBody data(유저 정보) + UserResponseDto data = UserMapper.data(savedUser); - return UserMapper.signupResponseDto(userResponseDto); + return UserMapper.signupResponse(data); } // 로그인 - public LoginResponseDto login(LoginRequestDto dto){ + public ApiResponseDto login(RequestDto dto){ String username = dto.getUsername(); String password = dto.getPassword(); User user = userRepository.findByUsername(username).orElseThrow( - () -> new IllegalArgumentException("아이디가 일치하지 않습니다.") + () -> new CustomException(ErrorCode.BAD_REQUEST) ); if(!passwordEncoder.matches(password,user.getPassword())){ - throw new IllegalArgumentException("비밀번호가 일치하지 않습니다"); + throw new CustomException(ErrorCode.BAD_REQUEST); } // JWT Token String token = jwtUtil.generateToken(user); - // data + // ResponseBody data(Token) Tokeninfo data = UserMapper.token(token); - return UserMapper.LoginResponseDto(data); + return UserMapper.LoginResponse(data); + } + + + // 회원 정보 조회 + public ApiResponseDto select(HttpServletRequest request){ + + // 요청 헤더에서 토큰 가져오기 + String authorizationHeader = request.getHeader("Authorization"); + String token = authorizationHeader.substring(7); + + // 토큰에서 Id 가져오기 + Long userId = jwtUtil.extractId(token); + + User user = userRepository.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + UserResponseDto data = UserMapper.data(user); + + return UserMapper.selectResponse(data); } } From 5bb048b05c48507bc79291130f593cd2ec66f396 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 10:07:50 +0900 Subject: [PATCH 021/123] =?UTF-8?q?feat=20:=20Task=20Controller=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/task/controller/.gitkeep | 0 .../task/controller/TaskController.java | 89 +++++++++++++++++++ .../onederful/domain/task/dto/.gitkeep | 0 .../onederful/domain/task/repository/.gitkeep | 0 .../onederful/domain/task/service/.gitkeep | 0 5 files changed, 89 insertions(+) delete mode 100644 src/main/java/com/example/onederful/domain/task/controller/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/task/controller/TaskController.java delete mode 100644 src/main/java/com/example/onederful/domain/task/dto/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/task/repository/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/task/service/.gitkeep diff --git a/src/main/java/com/example/onederful/domain/task/controller/.gitkeep b/src/main/java/com/example/onederful/domain/task/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java new file mode 100644 index 0000000..cec2d7e --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -0,0 +1,89 @@ +package com.example.onederful.domain.task.controller; + +import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.response.CommonResponse; +import com.example.onederful.domain.task.dto.response.TaskResponse; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.task.service.TaskService; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotNull; +import java.time.LocalDateTime; +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.Direction; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +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; + +@RestController +@Validated +@RequiredArgsConstructor +@RequestMapping("/api/tasks") +public class TaskController { + + private final TaskService taskService; + + @PostMapping + public ResponseEntity> createTask( + @RequestBody @Valid TaskSaveRequest request) { + + taskService.createTask(request); + return ResponseEntity.ok( + CommonResponse.create(true, "업무 생성 성공", null, LocalDateTime.now())); + } + + @GetMapping("/{id}") + public ResponseEntity> findTask(@PathVariable @NotNull Long id) { + + TaskResponse response = taskService.findTask(id); + + return ResponseEntity.ok( + CommonResponse.create(true, "업무 상세조회 성공", response, LocalDateTime.now())); + } + + @GetMapping + public ResponseEntity>> findTasks( + @RequestParam(defaultValue = "1") @Min(1) int page, + @RequestParam(defaultValue = "5") @Min(5) int size, + @RequestParam(defaultValue = "") String keyword, + @RequestParam(defaultValue = "TODO") ProcessStatus status + ) { + Pageable pageable = PageRequest.of(page - 1, size, Direction.ASC, "dueAt"); + + Page response = taskService.findTasks(pageable, keyword, + status); + + return ResponseEntity.ok( + CommonResponse.create(true, "업무 리스트 조회 성공", response, LocalDateTime.now())); + } + + @DeleteMapping("/{id}") + public ResponseEntity> deleteTask(@PathVariable @NotNull Long id) { + + taskService.deleteTask(id); + + return ResponseEntity.ok( + CommonResponse.create(true, "업무 삭제 성공", null, LocalDateTime.now())); + } + + @PutMapping("/{id}") + public ResponseEntity> updateTask(@PathVariable @NotNull Long id, + @RequestBody @Valid TaskSaveRequest request) { + + taskService.updateTask(id, request); + + return ResponseEntity.ok( + CommonResponse.create(true, "업무 수정 성공", null, LocalDateTime.now())); + } +} diff --git a/src/main/java/com/example/onederful/domain/task/dto/.gitkeep b/src/main/java/com/example/onederful/domain/task/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/task/repository/.gitkeep b/src/main/java/com/example/onederful/domain/task/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/task/service/.gitkeep b/src/main/java/com/example/onederful/domain/task/service/.gitkeep deleted file mode 100644 index e69de29..0000000 From 108775cf3614d637425c59b7f1fb72b73798e5e5 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 10:36:20 +0900 Subject: [PATCH 022/123] =?UTF-8?q?feat=20:=20Task=20=EB=B9=84=EC=A6=88?= =?UTF-8?q?=EB=8B=88=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EA=B5=AC=ED=98=84=20?= =?UTF-8?q?task=20create,=20update,=20soft=20delete,=20filter=20pagination?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=20=EC=A1=B0=EA=B1=B4=20=EC=B2=98=EB=A6=AC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84=20(=EC=83=81=ED=83=9C=20=EB=B3=80=EA=B2=BD?= =?UTF-8?q?=20=EC=8B=9C=20=EC=9D=B4=EC=A0=84=20=EC=83=81=ED=83=9C=EB=A1=9C?= =?UTF-8?q?=20=EB=8F=8C=EC=95=84=EA=B0=88=20=EC=88=98=20=EC=97=86=EC=9D=8C?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/task/service/TaskService.java | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/task/service/TaskService.java diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java new file mode 100644 index 0000000..aa886f3 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -0,0 +1,102 @@ +package com.example.onederful.domain.task.service; + +import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.response.TaskResponse; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.task.repository.TaskRepository; +import com.example.onederful.domain.task.repository.UserRepository; +import com.example.onederful.domain.user.entity.User; +import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.server.ResponseStatusException; + +@Service +@RequiredArgsConstructor +public class TaskService { + + private final TaskRepository taskRepository; + + // 유저 레포지토리 임의로 task domain 내부 작성 + private final UserRepository userRepository; + + @Transactional + public void createTask(TaskSaveRequest request) { + + User manager = userRepository.findById(request.getManagerId()).orElseThrow(); + + // user (생성한 사람은 추후 로그인 연동 후 수정 예정) + Task task = Task.builder() + .title(request.getTitle()) + .content(request.getContent()) + .priority(request.getPriority()) + .status(request.getStatus()) + .manager(manager) + .user(manager) + .status(ProcessStatus.TODO) + .dueAt(request.getDueAt().atStartOfDay()) + .build(); + + taskRepository.save(task); + } + + @Transactional(readOnly = true) + public TaskResponse findTask(Long id) { + + Task task = taskRepository.findById(id).orElseThrow(); + + return TaskResponse.of(task); + } + + @Transactional(readOnly = true) + public Page findTasks(Pageable pageable, String keyword, ProcessStatus status) { + + Page tasks = taskRepository.findTasks(keyword, status, pageable); + + return tasks.map(TaskResponse::of); + } + + @Transactional + public void deleteTask(Long id) { + + // 권한 검사는 로그인 병합 이후 + + Task task = taskRepository.findById(id).orElseThrow(); + task.delete(); + } + + @Transactional + public void updateTask(Long id, TaskSaveRequest request) { + + // 권한 검사는 로그인 병합 이후 + + Task task = taskRepository.findById(id).orElseThrow(); + User manager = userRepository.findById(request.getManagerId()).orElseThrow(); + + if (task.getStatus() == ProcessStatus.DONE) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "DONE 상태는 이전 상태로 변경 할 수 없습니다."); + } + + if (task.getStatus() == ProcessStatus.TODO) { + if (request.getStatus() != ProcessStatus.IN_PROGRESS) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "TODO -> IN_PROCESS으로만 상태 변경이 가능합니다."); + } + } + + if (task.getStatus() == ProcessStatus.IN_PROGRESS) { + if (request.getStatus() != ProcessStatus.DONE) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "IN_PROCESS -> DONE으로만 상태 변경이 가능합니다."); + } + } + + task.updateTask(request.getTitle(), request.getContent(), request.getPriority(), manager, + request.getDueAt().atStartOfDay(), request.getStatus()); + } +} From 32a0fa0830e8cd8cbddb519600b19d7b6d401b64 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 14:50:30 +0900 Subject: [PATCH 023/123] =?UTF-8?q?feat=20:=20=EB=8F=84=EC=A0=84=20?= =?UTF-8?q?=EA=B3=BC=EC=A0=9C=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EC=B6=B0=20=EB=AA=85=EC=B9=AD=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 --- onederful.sql | 72 +++++++++---------- .../com/example/onederful/config/.gitkeep | 0 .../onederful/domain/user/controller/.gitkeep | 0 .../onederful/domain/user/dto/.gitkeep | 0 .../onederful/domain/user/repository/.gitkeep | 0 .../onederful/domain/user/service/.gitkeep | 0 .../com/example/onederful/exception/.gitkeep | 0 .../com/example/onederful/filter/.gitkeep | 0 .../com/example/onederful/security/.gitkeep | 0 9 files changed, 36 insertions(+), 36 deletions(-) delete mode 100644 src/main/java/com/example/onederful/config/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/user/controller/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/user/dto/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/user/repository/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/user/service/.gitkeep delete mode 100644 src/main/java/com/example/onederful/exception/.gitkeep delete mode 100644 src/main/java/com/example/onederful/filter/.gitkeep delete mode 100644 src/main/java/com/example/onederful/security/.gitkeep diff --git a/onederful.sql b/onederful.sql index 6ea1dfc..8188ba5 100644 --- a/onederful.sql +++ b/onederful.sql @@ -1,62 +1,62 @@ CREATE TABLE users ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '사용자 식별자', - username VARCHAR(100) NOT NULL UNIQUE COMMENT '아이디', - email VARCHAR(100) NOT NULL UNIQUE COMMENT '이메일', - password VARCHAR(255) NOT NULL COMMENT '비밀번호', - name VARCHAR(100) NOT NULL COMMENT '이름', - role VARCHAR(50) NOT NULL COMMENT '권한 (ENUM)', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '사용자 식별자', + username VARCHAR(100) NOT NULL UNIQUE COMMENT '아이디', + email VARCHAR(100) NOT NULL UNIQUE COMMENT '이메일', + password VARCHAR(255) NOT NULL COMMENT '비밀번호', + name VARCHAR(100) NOT NULL COMMENT '이름', + role VARCHAR(50) NOT NULL COMMENT '권한 (ENUM)', created_at DATETIME COMMENT '생성일자', updated_at DATETIME COMMENT '수정일자', deleted_at DATETIME COMMENT '삭제날짜', - is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부' + is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부' ); CREATE TABLE tasks ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '업무 식별자', - title VARCHAR(100) NOT NULL COMMENT '제목', - content TEXT NOT NULL COMMENT '설명', - priority VARCHAR(100) NOT NULL COMMENT '우선순위 식별자 (ENUM)', - manager_id BIGINT NOT NULL COMMENT '담당자 식별자 (FK)', - user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', - status VARCHAR(100) NOT NULL COMMENT '태스크 상태 (ENUM)', - due_at DATETIME COMMENT '마감일자', - started_at DATETIME COMMENT '시작일자', - created_at DATETIME COMMENT '생성일자', - updated_at DATETIME COMMENT '수정일자', - deleted_at DATETIME COMMENT '삭제날짜', - is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '업무 식별자', + title VARCHAR(100) NOT NULL COMMENT '제목', + description TEXT NOT NULL COMMENT '설명', + priority VARCHAR(100) NOT NULL COMMENT '우선순위 식별자 (ENUM)', + manager_id BIGINT NOT NULL COMMENT '담당자 식별자 (FK)', + user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', + status VARCHAR(100) NOT NULL COMMENT '태스크 상태 (ENUM)', + due_date DATETIME COMMENT '마감일자', + started_at DATETIME COMMENT '시작일자', + created_at DATETIME COMMENT '생성일자', + updated_at DATETIME COMMENT '수정일자', + deleted_at DATETIME COMMENT '삭제날짜', + is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부', - FOREIGN KEY (manager_id) REFERENCES users(id) ON DELETE CASCADE, - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE + FOREIGN KEY (manager_id) REFERENCES users (id) ON DELETE CASCADE, + FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); CREATE TABLE comments ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '댓글 식별자', - content TEXT NOT NULL COMMENT '댓글 내용', - task_id BIGINT NOT NULL COMMENT '업무 식별자 (FK)', - user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '댓글 식별자', + content TEXT NOT NULL COMMENT '댓글 내용', + task_id BIGINT NOT NULL COMMENT '업무 식별자 (FK)', + user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', created_at DATETIME COMMENT '생성일자', updated_at DATETIME COMMENT '수정일자', deleted_at DATETIME COMMENT '삭제날짜', is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부', - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, - FOREIGN KEY (task_id) REFERENCES tasks(id) ON DELETE CASCADE + FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE, + FOREIGN KEY (task_id) REFERENCES tasks (id) ON DELETE CASCADE ); CREATE TABLE logs ( - id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '로그 식별자', - user_id BIGINT NOT NULL COMMENT '사용자 식별자 (FK)', - activity VARCHAR(100) NOT NULL COMMENT '활동 유형', - ip_address VARCHAR(100) NOT NULL COMMENT 'ip 주소', - method VARCHAR(100) NOT NULL COMMENT '요청 메서드 (ENUM)', - target_id BIGINT NOT NULL COMMENT '작업 대상 식별자', + id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT '로그 식별자', + user_id BIGINT NOT NULL COMMENT '사용자 식별자 (FK)', + activity VARCHAR(100) NOT NULL COMMENT '활동 유형', + ip_address VARCHAR(100) NOT NULL COMMENT 'ip 주소', + method VARCHAR(100) NOT NULL COMMENT '요청 메서드 (ENUM)', + target_id BIGINT NOT NULL COMMENT '작업 대상 식별자', request_url VARCHAR(200) NOT NULL COMMENT '로그 요청 url', - created_at DATETIME COMMENT '생성일자', + created_at DATETIME COMMENT '생성일자', - FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE + FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); diff --git a/src/main/java/com/example/onederful/config/.gitkeep b/src/main/java/com/example/onederful/config/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/user/controller/.gitkeep b/src/main/java/com/example/onederful/domain/user/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/user/dto/.gitkeep b/src/main/java/com/example/onederful/domain/user/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/user/repository/.gitkeep b/src/main/java/com/example/onederful/domain/user/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/user/service/.gitkeep b/src/main/java/com/example/onederful/domain/user/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/exception/.gitkeep b/src/main/java/com/example/onederful/exception/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/filter/.gitkeep b/src/main/java/com/example/onederful/filter/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/security/.gitkeep b/src/main/java/com/example/onederful/security/.gitkeep deleted file mode 100644 index e69de29..0000000 From 7defe72b8028b0b3031e3d26a5c7ffb28904483d Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 14:51:28 +0900 Subject: [PATCH 024/123] refactor : src/main/java/com/example/onederful/security/JwtUtil.java --- .../domain/task/controller/TaskController.java | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java index cec2d7e..4c2ab27 100644 --- a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -8,7 +8,7 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; -import java.time.LocalDateTime; +import java.time.OffsetDateTime; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -40,7 +40,8 @@ public ResponseEntity> createTask( taskService.createTask(request); return ResponseEntity.ok( - CommonResponse.create(true, "업무 생성 성공", null, LocalDateTime.now())); + CommonResponse.create(true, "업무 생성 성공", null, + OffsetDateTime.now())); } @GetMapping("/{id}") @@ -49,7 +50,8 @@ public ResponseEntity> findTask(@PathVariable @NotN TaskResponse response = taskService.findTask(id); return ResponseEntity.ok( - CommonResponse.create(true, "업무 상세조회 성공", response, LocalDateTime.now())); + CommonResponse.create(true, "업무 상세조회 성공", response, + OffsetDateTime.now())); } @GetMapping @@ -59,13 +61,14 @@ public ResponseEntity>> findTasks( @RequestParam(defaultValue = "") String keyword, @RequestParam(defaultValue = "TODO") ProcessStatus status ) { - Pageable pageable = PageRequest.of(page - 1, size, Direction.ASC, "dueAt"); + Pageable pageable = PageRequest.of(page - 1, size, Direction.ASC, "dueDate"); Page response = taskService.findTasks(pageable, keyword, status); return ResponseEntity.ok( - CommonResponse.create(true, "업무 리스트 조회 성공", response, LocalDateTime.now())); + CommonResponse.create(true, "업무 리스트 조회 성공", response, + OffsetDateTime.now())); } @DeleteMapping("/{id}") @@ -74,7 +77,8 @@ public ResponseEntity> deleteTask(@PathVariable @NotNull Lo taskService.deleteTask(id); return ResponseEntity.ok( - CommonResponse.create(true, "업무 삭제 성공", null, LocalDateTime.now())); + CommonResponse.create(true, "업무 삭제 성공", null, + OffsetDateTime.now())); } @PutMapping("/{id}") @@ -84,6 +88,6 @@ public ResponseEntity> updateTask(@PathVariable @NotNull Lo taskService.updateTask(id, request); return ResponseEntity.ok( - CommonResponse.create(true, "업무 수정 성공", null, LocalDateTime.now())); + CommonResponse.create(true, "업무 수정 성공", null, OffsetDateTime.now())); } } From db37ac3d8002ada2b8d82f989f92fa88a9cf980c Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 14:52:38 +0900 Subject: [PATCH 025/123] =?UTF-8?q?refactor=20:=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20Id=20=EC=B6=94=EC=B6=9C=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20token=20->=20HttpServletRequest=20?= =?UTF-8?q?=ED=83=80=EC=9E=85=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/service/UserService.java | 31 ++++--- .../example/onederful/security/JwtUtil.java | 91 ++++++++++--------- 2 files changed, 63 insertions(+), 59 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/service/UserService.java b/src/main/java/com/example/onederful/domain/user/service/UserService.java index e3dce19..a364b9c 100644 --- a/src/main/java/com/example/onederful/domain/user/service/UserService.java +++ b/src/main/java/com/example/onederful/domain/user/service/UserService.java @@ -2,7 +2,10 @@ import com.example.onederful.config.PasswordEncoder; import com.example.onederful.domain.user.common.UserMapper; -import com.example.onederful.domain.user.dto.*; +import com.example.onederful.domain.user.dto.ApiResponseDto; +import com.example.onederful.domain.user.dto.RequestDto; +import com.example.onederful.domain.user.dto.Tokeninfo; +import com.example.onederful.domain.user.dto.UserResponseDto; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; import com.example.onederful.exception.CustomException; @@ -21,11 +24,13 @@ public class UserService { private final JwtUtil jwtUtil; // 회원가입 - public ApiResponseDto signup(RequestDto dto){ - + public ApiResponseDto signup(RequestDto dto) { + // 이메일 중복 확인 userRepository.findByEmail(dto.getEmail()).ifPresent( - user -> {throw new CustomException(ErrorCode.DUPLICATE_USER);} + user -> { + throw new CustomException(ErrorCode.DUPLICATE_USER); + } ); // Dto → Entity @@ -44,15 +49,15 @@ public ApiResponseDto signup(RequestDto dto){ // 로그인 - public ApiResponseDto login(RequestDto dto){ + public ApiResponseDto login(RequestDto dto) { String username = dto.getUsername(); String password = dto.getPassword(); User user = userRepository.findByUsername(username).orElseThrow( - () -> new CustomException(ErrorCode.BAD_REQUEST) + () -> new CustomException(ErrorCode.BAD_REQUEST) ); - - if(!passwordEncoder.matches(password,user.getPassword())){ + + if (!passwordEncoder.matches(password, user.getPassword())) { throw new CustomException(ErrorCode.BAD_REQUEST); } @@ -67,17 +72,13 @@ public ApiResponseDto login(RequestDto dto){ // 회원 정보 조회 - public ApiResponseDto select(HttpServletRequest request){ - - // 요청 헤더에서 토큰 가져오기 - String authorizationHeader = request.getHeader("Authorization"); - String token = authorizationHeader.substring(7); + public ApiResponseDto select(HttpServletRequest request) { // 토큰에서 Id 가져오기 - Long userId = jwtUtil.extractId(token); + Long userId = jwtUtil.extractId(request); User user = userRepository.findById(userId).orElseThrow( - () -> new CustomException(ErrorCode.UNAUTHORIZED) + () -> new CustomException(ErrorCode.UNAUTHORIZED) ); UserResponseDto data = UserMapper.data(user); diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java index 6b73706..e490174 100644 --- a/src/main/java/com/example/onederful/security/JwtUtil.java +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -1,17 +1,22 @@ package com.example.onederful.security; import com.example.onederful.domain.user.entity.User; -import io.jsonwebtoken.*; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.UnsupportedJwtException; import io.jsonwebtoken.security.Keys; import io.jsonwebtoken.security.SecurityException; import jakarta.annotation.PostConstruct; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.stereotype.Component; - +import jakarta.servlet.http.HttpServletRequest; import java.security.Key; import java.util.Base64; import java.util.Date; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; @Slf4j @Component @@ -19,74 +24,72 @@ public class JwtUtil { // JWT Token 접두사 public final static String BEARER_PREFIX = "Bearer "; - + // JWT 서명 알고리즘 + private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; // JWT Token 만료시간 @Value("${jwt.expiration}") public Long expirationTime; - - // JWT 서명 알고리즘 - private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; - // 비밀 키 @Value("${jwt.secret.key}") private String secretKey; - + // 실제 서명에서 사용할 키 객체 private Key key; /** - * 빈 초기화 메서드 - * - 애플리케이션 실행 시 비밀키를 Base64로 디코딩 하여 key 객체를 초기화 + * 빈 초기화 메서드 - 애플리케이션 실행 시 비밀키를 Base64로 디코딩 하여 key 객체를 초기화 */ @PostConstruct - public void init(){ - byte [] bytes = Base64.getDecoder().decode(secretKey); + public void init() { + byte[] bytes = Base64.getDecoder().decode(secretKey); key = Keys.hmacShaKeyFor(bytes); } /** * JWT 토큰 생성 + * * @param user User Entity * @return 생성된 JWT 토큰 */ - public String generateToken(User user){ + public String generateToken(User user) { Long id = user.getId(); String username = user.getUsername(); Date date = new Date(); return BEARER_PREFIX + - Jwts.builder() - .setSubject(username) - .claim("id",id) - .setIssuedAt(date) - .setExpiration(new Date(date.getTime()+ expirationTime)) - .signWith(key,signatureAlgorithm) - .compact(); + Jwts.builder() + .setSubject(username) + .claim("id", id) + .setIssuedAt(date) + .setExpiration(new Date(date.getTime() + expirationTime)) + .signWith(key, signatureAlgorithm) + .compact(); } /** * JWT 토큰 유효성 검증 + * * @param token JWT 토큰 * @return 토큰의 유효성 여부 (true : 유효, false : 유효하지 않음) */ - public boolean validateToken(String token){ + public boolean validateToken(String token) { try { Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token); + .setSigningKey(key) + .build() + .parseClaimsJws(token); return true; - }catch (SecurityException | MalformedJwtException e){ + } catch (SecurityException | MalformedJwtException e) { log.error("Invalid JWT signature, 유효하지 않은 JWT 서명입니다."); - }catch (ExpiredJwtException e){ + } catch (ExpiredJwtException e) { log.error("Expired JWT token, 만료된 JWT token 입니다.", e); - }catch (UnsupportedJwtException e){ + } catch (UnsupportedJwtException e) { log.error("Unsupported JWT token, 지원되지 않는 JWT 토큰 입니다.", e); - }catch (IllegalArgumentException e){ + } catch (IllegalArgumentException e) { log.error("JWT claims is empty, 잘못된 JWT 토큰 입니다.", e); } return false; @@ -94,27 +97,27 @@ public boolean validateToken(String token){ /** * Token에 존재하는 모든 클레임(페이로드 값)을 추출 + * * @param token 검증된 JWT 토큰 (로그인 한 상태) * @return 클라임 객체 */ - public Claims extractAllClaims(String token){ + public Claims extractAllClaims(String token) { return Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .getBody(); + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); } /** * Token에 저장된 ID(기본키) 가져오기 - * @param token 검증된 JWT 토큰 (로그인 한 상태) - * @return ID값 + * + * @param request 인증 완료 HttpServletRequest + * @return ID값 */ - public Long extractId(String token){ - return extractAllClaims(token).get("id",Long.class); + public Long extractId(HttpServletRequest request) { + String authorizationHeader = request.getHeader("Authorization"); + String token = authorizationHeader.substring(7); + return extractAllClaims(token).get("id", Long.class); } - - - - } From e697cc1ac90b8db61d985397703169c16950d2cf Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 14:53:53 +0900 Subject: [PATCH 026/123] =?UTF-8?q?refactor=20:=20Task=20=EB=8F=84?= =?UTF-8?q?=EC=A0=84=EA=B3=BC=EC=A0=9C=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=EC=97=90=20=EB=A7=9E=EC=B6=B0=20=EC=88=98=EC=A0=95=20DB=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(content=20->=20description,=20dueAt=20->=20dueDate?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/dto/request/TaskSaveRequest.java | 34 +++++++++++++++ .../task/dto/response/CommonResponse.java | 15 +++++++ .../task/dto/response/TaskResponse.java | 43 +++++++++++++++++++ .../onederful/domain/task/entity/Task.java | 35 +++++++++++---- .../task/repository/TaskRepository.java | 18 ++++++++ .../domain/task/service/TaskService.java | 20 ++++----- 6 files changed, 145 insertions(+), 20 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java create mode 100644 src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java create mode 100644 src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java create mode 100644 src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java new file mode 100644 index 0000000..d66097f --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java @@ -0,0 +1,34 @@ +package com.example.onederful.domain.task.dto.request; + +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.OffsetDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TaskSaveRequest { + + @NotBlank(message = "업무 제목은 필수 항목입니다.") + private String title; + + @NotBlank(message = "업무 내용은 필수 항목입니다.") + private String description; + + @NotNull(message = "업무의 우선순위는 필수 항목입니다.") + private Priority priority; + + @NotNull(message = "관리자 선택은 필수 항목입니다.") + private Long managerId; + + @NotNull(message = "업무의 상태는 필수 항목입니다.") + private ProcessStatus status; + + @NotNull(message = "마감일은 필수 항목입니다.") + @FutureOrPresent(message = "마감일은 오늘이후만 가능합니다.") + private OffsetDateTime dueDate; +} diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java b/src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java new file mode 100644 index 0000000..b308a5e --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java @@ -0,0 +1,15 @@ +package com.example.onederful.domain.task.dto.response; + +import java.time.OffsetDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor(staticName = "create") +public class CommonResponse { + + private boolean success; + private String message; + private T data; + private OffsetDateTime timestamp; +} diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java b/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java new file mode 100644 index 0000000..a16f2b5 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java @@ -0,0 +1,43 @@ +package com.example.onederful.domain.task.dto.response; + +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.ProcessStatus; +import java.time.OffsetDateTime; +import java.time.ZoneOffset; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TaskResponse { + + private Long id; + private String title; + private String description; + private String priority; + private ProcessStatus status; + private String managerName; + + private OffsetDateTime dueDate; + private OffsetDateTime createdAt; + private OffsetDateTime updatedAt; + + public static TaskResponse of(Task task) { + return TaskResponse.builder() + .id(task.getId()) + .title(task.getTitle()) + .description(task.getDescription()) + .status(task.getStatus()) + .priority(task.getPriority().name()) + .managerName(task.getManager().getName()) + .dueDate(task.getDueDate().atOffset(ZoneOffset.UTC)) + .createdAt(task.getCreatedAt().atOffset(ZoneOffset.UTC)) + .updatedAt(task.getUpdatedAt().atOffset(ZoneOffset.UTC)) + .build(); + } +} diff --git a/src/main/java/com/example/onederful/domain/task/entity/Task.java b/src/main/java/com/example/onederful/domain/task/entity/Task.java index 539f035..67f89e9 100644 --- a/src/main/java/com/example/onederful/domain/task/entity/Task.java +++ b/src/main/java/com/example/onederful/domain/task/entity/Task.java @@ -22,6 +22,7 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLRestriction; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -30,6 +31,7 @@ @Builder @Getter @Table(name = "tasks") +@SQLRestriction("is_deleted = false") @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) @@ -42,29 +44,29 @@ public class Task { @Column(name = "title", nullable = false) private String title; - @Column(name = "content", nullable = false) - private String content; + @Column(name = "description", nullable = false) + private String description; @Enumerated(EnumType.STRING) @Column(name = "priority", nullable = false) private Priority priority; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name="manager_id", nullable = false) + @JoinColumn(name = "manager_id", nullable = false) private User manager; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name="user_id", nullable = false) + @JoinColumn(name = "user_id", nullable = false) private User user; @Enumerated(EnumType.STRING) - @Column(name="status", nullable = false) + @Column(name = "status", nullable = false) private ProcessStatus status; - @Column(name="due_at", nullable = false) - private LocalDateTime dueAt; + @Column(name = "due_date", nullable = false) + private LocalDateTime dueDate; - @Column(name="started_at", nullable=false) + @Column(name = "started_at", nullable = false) private LocalDateTime startedAt; @CreatedDate @@ -79,6 +81,21 @@ public class Task { private LocalDateTime deletedAt; @Builder.Default - @Column(name="is_deleted", nullable = false) + @Column(name = "is_deleted", nullable = false) private Boolean isDeleted = false; + + public void updateTask(String title, String content, Priority priority, User manager, + LocalDateTime dueDate, ProcessStatus status) { + this.title = title; + this.description = content; + this.priority = priority; + this.manager = manager; + this.dueDate = dueDate; + this.status = status; + } + + public void delete() { + this.isDeleted = true; + this.deletedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java b/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java new file mode 100644 index 0000000..8044466 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java @@ -0,0 +1,18 @@ +package com.example.onederful.domain.task.repository; + +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.ProcessStatus; +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.data.repository.query.Param; +import org.springframework.stereotype.Repository; + +@Repository +public interface TaskRepository extends JpaRepository { + + @Query("SELECT t FROM Task t WHERE (t.title LIKE %:keyword% OR t.description LIKE %:keyword%) AND t.status = :status") + Page findTasks(@Param("keyword") String keyword, @Param("status") ProcessStatus status, + Pageable pageable); +} diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index aa886f3..dbc4a32 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -5,8 +5,9 @@ import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.repository.TaskRepository; -import com.example.onederful.domain.task.repository.UserRepository; import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.security.JwtUtil; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -20,9 +21,8 @@ public class TaskService { private final TaskRepository taskRepository; - - // 유저 레포지토리 임의로 task domain 내부 작성 private final UserRepository userRepository; + private final JwtUtil jwtUtil; @Transactional public void createTask(TaskSaveRequest request) { @@ -32,13 +32,13 @@ public void createTask(TaskSaveRequest request) { // user (생성한 사람은 추후 로그인 연동 후 수정 예정) Task task = Task.builder() .title(request.getTitle()) - .content(request.getContent()) + .description(request.getDescription()) .priority(request.getPriority()) .status(request.getStatus()) .manager(manager) .user(manager) .status(ProcessStatus.TODO) - .dueAt(request.getDueAt().atStartOfDay()) + .dueDate(request.getDueDate().toLocalDateTime()) .build(); taskRepository.save(task); @@ -63,17 +63,14 @@ public Page findTasks(Pageable pageable, String keyword, ProcessSt @Transactional public void deleteTask(Long id) { - // 권한 검사는 로그인 병합 이후 - Task task = taskRepository.findById(id).orElseThrow(); + task.delete(); } @Transactional public void updateTask(Long id, TaskSaveRequest request) { - // 권한 검사는 로그인 병합 이후 - Task task = taskRepository.findById(id).orElseThrow(); User manager = userRepository.findById(request.getManagerId()).orElseThrow(); @@ -96,7 +93,8 @@ public void updateTask(Long id, TaskSaveRequest request) { } } - task.updateTask(request.getTitle(), request.getContent(), request.getPriority(), manager, - request.getDueAt().atStartOfDay(), request.getStatus()); + task.updateTask(request.getTitle(), request.getDescription(), request.getPriority(), + manager, + request.getDueDate().toLocalDateTime(), request.getStatus()); } } From 591f5d048c56d590f23ef37c27da1abecfe4b263 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 15:53:26 +0900 Subject: [PATCH 027/123] =?UTF-8?q?feat=20:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20managerId=20->=20assigneeId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- onederful.sql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/onederful.sql b/onederful.sql index 8188ba5..76bb0a9 100644 --- a/onederful.sql +++ b/onederful.sql @@ -18,7 +18,7 @@ CREATE TABLE tasks title VARCHAR(100) NOT NULL COMMENT '제목', description TEXT NOT NULL COMMENT '설명', priority VARCHAR(100) NOT NULL COMMENT '우선순위 식별자 (ENUM)', - manager_id BIGINT NOT NULL COMMENT '담당자 식별자 (FK)', + assignee_id BIGINT NOT NULL COMMENT '담당자 식별자 (FK)', user_id BIGINT NOT NULL COMMENT '작성자 식별자 (FK)', status VARCHAR(100) NOT NULL COMMENT '태스크 상태 (ENUM)', due_date DATETIME COMMENT '마감일자', @@ -28,7 +28,7 @@ CREATE TABLE tasks deleted_at DATETIME COMMENT '삭제날짜', is_deleted BOOLEAN NOT NULL DEFAULT FALSE COMMENT '삭제여부', - FOREIGN KEY (manager_id) REFERENCES users (id) ON DELETE CASCADE, + FOREIGN KEY (assignee_id) REFERENCES users (id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users (id) ON DELETE CASCADE ); From 6c137c1c4eb23e82bcd09ab8e70e8e46b489a8ab Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 15:54:09 +0900 Subject: [PATCH 028/123] =?UTF-8?q?feat=20:=20Task=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?/=20=EC=88=98=EC=A0=95=20DTO=20=EB=B6=84=EB=A6=AC=20=EC=9A=94?= =?UTF-8?q?=EA=B5=AC=EC=82=AC=ED=95=AD=20=EB=B3=80=EA=B2=BD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=A5=B8=20DTO=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/dto/request/TaskSaveRequest.java | 6 +--- .../task/dto/request/TaskUpdateRequest.java | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java index d66097f..fc7fd43 100644 --- a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java +++ b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java @@ -1,7 +1,6 @@ package com.example.onederful.domain.task.dto.request; import com.example.onederful.domain.task.enums.Priority; -import com.example.onederful.domain.task.enums.ProcessStatus; import jakarta.validation.constraints.FutureOrPresent; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; @@ -23,10 +22,7 @@ public class TaskSaveRequest { private Priority priority; @NotNull(message = "관리자 선택은 필수 항목입니다.") - private Long managerId; - - @NotNull(message = "업무의 상태는 필수 항목입니다.") - private ProcessStatus status; + private Long assigneeId; @NotNull(message = "마감일은 필수 항목입니다.") @FutureOrPresent(message = "마감일은 오늘이후만 가능합니다.") diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java new file mode 100644 index 0000000..9633896 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java @@ -0,0 +1,34 @@ +package com.example.onederful.domain.task.dto.request; + +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import jakarta.validation.constraints.FutureOrPresent; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.OffsetDateTime; +import lombok.AllArgsConstructor; +import lombok.Getter; + +@Getter +@AllArgsConstructor +public class TaskUpdateRequest { + + @NotBlank(message = "업무 제목은 필수 항목입니다.") + private String title; + + @NotBlank(message = "업무 내용은 필수 항목입니다.") + private String description; + + @NotNull(message = "업무의 우선순위는 필수 항목입니다.") + private Priority priority; + + @NotNull(message = "관리자 선택은 필수 항목입니다.") + private Long assigneeId; + + @NotNull(message = "업무의 상태는 필수 항목입니다.") + private ProcessStatus status; + + @NotNull(message = "마감일은 필수 항목입니다.") + @FutureOrPresent(message = "마감일은 오늘이후만 가능합니다.") + private OffsetDateTime dueDate; +} From 41585b9f80804f46c48b7e4239a5f3c48d8394bf Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 15:55:01 +0900 Subject: [PATCH 029/123] =?UTF-8?q?feat=20:=20Task=20=EC=9D=91=EB=8B=B5=20?= =?UTF-8?q?asssignee=20DTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/dto/response/TaskAssignee.java | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/task/dto/response/TaskAssignee.java diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/TaskAssignee.java b/src/main/java/com/example/onederful/domain/task/dto/response/TaskAssignee.java new file mode 100644 index 0000000..4b59157 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/response/TaskAssignee.java @@ -0,0 +1,29 @@ +package com.example.onederful.domain.task.dto.response; + +import com.example.onederful.domain.user.entity.User; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class TaskAssignee { + + private Long id; + private String username; + private String name; + private String email; + + public static TaskAssignee of(User user) { + return TaskAssignee.builder() + .id(user.getId()) + .username(user.getUsername()) + .name(user.getName()) + .email(user.getEmail()) + .build(); + } +} From d72a7daded3786078d71698a85208b96067db3b7 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 15:55:20 +0900 Subject: [PATCH 030/123] =?UTF-8?q?feat=20:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20DTO=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/task/dto/response/TaskResponse.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java b/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java index a16f2b5..2b3b802 100644 --- a/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java +++ b/src/main/java/com/example/onederful/domain/task/dto/response/TaskResponse.java @@ -1,6 +1,7 @@ package com.example.onederful.domain.task.dto.response; import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.Priority; import com.example.onederful.domain.task.enums.ProcessStatus; import java.time.OffsetDateTime; import java.time.ZoneOffset; @@ -19,9 +20,10 @@ public class TaskResponse { private Long id; private String title; private String description; - private String priority; + private Priority priority; private ProcessStatus status; - private String managerName; + private Long assigneeId; + private TaskAssignee assignee; private OffsetDateTime dueDate; private OffsetDateTime createdAt; @@ -33,8 +35,9 @@ public static TaskResponse of(Task task) { .title(task.getTitle()) .description(task.getDescription()) .status(task.getStatus()) - .priority(task.getPriority().name()) - .managerName(task.getManager().getName()) + .priority(task.getPriority()) + .assigneeId(task.getAssignee().getId()) + .assignee(TaskAssignee.of(task.getAssignee())) .dueDate(task.getDueDate().atOffset(ZoneOffset.UTC)) .createdAt(task.getCreatedAt().atOffset(ZoneOffset.UTC)) .updatedAt(task.getUpdatedAt().atOffset(ZoneOffset.UTC)) From 2730e8cc8c25098b74226a01d48bd0f3770d0990 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 15:55:48 +0900 Subject: [PATCH 031/123] =?UTF-8?q?refactor=20:=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=A5=B8=20Entity=20=EB=B3=80=EA=B2=BD=20managerId=20->=20assi?= =?UTF-8?q?gneeId?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/onederful/domain/task/entity/Task.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/entity/Task.java b/src/main/java/com/example/onederful/domain/task/entity/Task.java index 67f89e9..7cf5a20 100644 --- a/src/main/java/com/example/onederful/domain/task/entity/Task.java +++ b/src/main/java/com/example/onederful/domain/task/entity/Task.java @@ -52,8 +52,8 @@ public class Task { private Priority priority; @ManyToOne(fetch = FetchType.LAZY) - @JoinColumn(name = "manager_id", nullable = false) - private User manager; + @JoinColumn(name = "assignee_id", nullable = false) + private User assignee; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "user_id", nullable = false) @@ -84,12 +84,12 @@ public class Task { @Column(name = "is_deleted", nullable = false) private Boolean isDeleted = false; - public void updateTask(String title, String content, Priority priority, User manager, + public void updateTask(String title, String content, Priority priority, User assignee, LocalDateTime dueDate, ProcessStatus status) { this.title = title; this.description = content; this.priority = priority; - this.manager = manager; + this.assignee = assignee; this.dueDate = dueDate; this.status = status; } From 386a74c109d3cbd269dc33b9e62c9643e4bb86ef Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 15:56:17 +0900 Subject: [PATCH 032/123] =?UTF-8?q?feat=20:=20create,=20update=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=A1=B4=EC=9E=AC?= =?UTF-8?q?=ED=95=A8=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?void=20->=20TaskResponse=20=EC=9D=91=EB=8B=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/controller/TaskController.java | 19 ++++++++------- .../domain/task/service/TaskService.java | 24 ++++++++++++------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java index 4c2ab27..ea4f7a5 100644 --- a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -1,10 +1,12 @@ package com.example.onederful.domain.task.controller; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.request.TaskUpdateRequest; import com.example.onederful.domain.task.dto.response.CommonResponse; import com.example.onederful.domain.task.dto.response.TaskResponse; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.service.TaskService; +import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; @@ -35,12 +37,13 @@ public class TaskController { private final TaskService taskService; @PostMapping - public ResponseEntity> createTask( - @RequestBody @Valid TaskSaveRequest request) { + public ResponseEntity> createTask( + @RequestBody @Valid TaskSaveRequest request, HttpServletRequest httpServletRequest) { + + TaskResponse response = taskService.createTask(request, httpServletRequest); - taskService.createTask(request); return ResponseEntity.ok( - CommonResponse.create(true, "업무 생성 성공", null, + CommonResponse.create(true, "업무 생성 성공", response, OffsetDateTime.now())); } @@ -82,12 +85,12 @@ public ResponseEntity> deleteTask(@PathVariable @NotNull Lo } @PutMapping("/{id}") - public ResponseEntity> updateTask(@PathVariable @NotNull Long id, - @RequestBody @Valid TaskSaveRequest request) { + public ResponseEntity> updateTask(@PathVariable @NotNull Long id, + @RequestBody @Valid TaskUpdateRequest request) { - taskService.updateTask(id, request); + TaskResponse response = taskService.updateTask(id, request); return ResponseEntity.ok( - CommonResponse.create(true, "업무 수정 성공", null, OffsetDateTime.now())); + CommonResponse.create(true, "업무 수정 성공", response, OffsetDateTime.now())); } } diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index dbc4a32..e8197ab 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -1,6 +1,7 @@ package com.example.onederful.domain.task.service; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.request.TaskUpdateRequest; import com.example.onederful.domain.task.dto.response.TaskResponse; import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.ProcessStatus; @@ -8,6 +9,7 @@ import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; import com.example.onederful.security.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -25,23 +27,27 @@ public class TaskService { private final JwtUtil jwtUtil; @Transactional - public void createTask(TaskSaveRequest request) { + public TaskResponse createTask(TaskSaveRequest request, HttpServletRequest httpServletRequest) { - User manager = userRepository.findById(request.getManagerId()).orElseThrow(); + Long userId = jwtUtil.extractId(httpServletRequest); + + User me = userRepository.findById(userId).orElseThrow(); + User manager = userRepository.findById(request.getAssigneeId()).orElseThrow(); // user (생성한 사람은 추후 로그인 연동 후 수정 예정) Task task = Task.builder() .title(request.getTitle()) .description(request.getDescription()) .priority(request.getPriority()) - .status(request.getStatus()) - .manager(manager) - .user(manager) + .assignee(manager) + .user(me) .status(ProcessStatus.TODO) .dueDate(request.getDueDate().toLocalDateTime()) .build(); taskRepository.save(task); + + return TaskResponse.of(task); } @Transactional(readOnly = true) @@ -69,10 +75,10 @@ public void deleteTask(Long id) { } @Transactional - public void updateTask(Long id, TaskSaveRequest request) { + public TaskResponse updateTask(Long id, TaskUpdateRequest request) { Task task = taskRepository.findById(id).orElseThrow(); - User manager = userRepository.findById(request.getManagerId()).orElseThrow(); + User assignee = userRepository.findById(request.getAssigneeId()).orElseThrow(); if (task.getStatus() == ProcessStatus.DONE) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, @@ -94,7 +100,9 @@ public void updateTask(Long id, TaskSaveRequest request) { } task.updateTask(request.getTitle(), request.getDescription(), request.getPriority(), - manager, + assignee, request.getDueDate().toLocalDateTime(), request.getStatus()); + + return TaskResponse.of(task); } } From 11aca9c51c2b9acc083e07a8d016689ca8f845dc Mon Sep 17 00:00:00 2001 From: saevit Date: Tue, 17 Jun 2025 16:14:41 +0900 Subject: [PATCH 033/123] =?UTF-8?q?feat:=20AOP=20=ED=99=9C=EB=8F=99=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B8=B0=EB=A1=9D=20=EA=B8=B0=EB=B3=B8=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B0=8F=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/LoggingAspect.java | 63 +++++++++++ .../onederful/domain/log/controller/.gitkeep | 0 .../domain/log/controller/LogController.java | 55 +++++++++ .../example/onederful/domain/log/dto/.gitkeep | 0 .../domain/log/dto/LogResponseDto.java | 39 +++++++ .../domain/log/dto/addLogTestDto.java | 10 ++ .../onederful/domain/log/enums/Activity.java | 26 ++++- .../onederful/domain/log/repository/.gitkeep | 0 .../domain/log/repository/LogRepository.java | 11 ++ .../log/repository/LogSpecification.java | 41 +++++++ .../onederful/domain/log/service/.gitkeep | 0 .../domain/log/service/LogService.java | 106 ++++++++++++++++++ 12 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/log/LoggingAspect.java delete mode 100644 src/main/java/com/example/onederful/domain/log/controller/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/controller/LogController.java delete mode 100644 src/main/java/com/example/onederful/domain/log/dto/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java create mode 100644 src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java delete mode 100644 src/main/java/com/example/onederful/domain/log/repository/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/repository/LogRepository.java create mode 100644 src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java delete mode 100644 src/main/java/com/example/onederful/domain/log/service/.gitkeep create mode 100644 src/main/java/com/example/onederful/domain/log/service/LogService.java diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java new file mode 100644 index 0000000..5b666d9 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -0,0 +1,63 @@ +package com.example.onederful.domain.log; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Pointcut; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.example.onederful.domain.log.enums.Method; +import com.example.onederful.domain.log.service.LogService; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; + +@Aspect +@Component +@RequiredArgsConstructor +public class LoggingAspect { + + private final LogService logService; + + @Pointcut("execution(* com.example..LogService.addLogTest1()) || execution(* com.example..LogService.addLogTest2())") + public void serviceMethods() {} + + // 생성, 수정, 삭제 + @AfterReturning(pointcut = "serviceMethods()", returning = "result") + public void logAfterReturning(JoinPoint joinPoint, Object result) { + System.out.println("메서드 정상 실행 후: 로그 기록"); + + // HttpServletRequest으로부터 요청 ip, 메서드, url + HttpServletRequest request = + ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); + + // if (request == null) 예외 처리 + + String ip = request.getRemoteAddr(); + String method = request.getMethod(); + Method enumMethod = Method.valueOf(method); + String url = request.getRequestURI(); + + // 로그 저장 + logService.saveLog(ip, enumMethod, url, result); + } + + // 상태 변경 + // @Around("serviceMethods()") + // public void logTaskStatusChange() { + // // 변경 전 task 상태 조회 + // taskService.findStatus(); + // + // // 메서드 실행 + // + // // 변경 후 tast 상태 조회 및 다른 정보들 뽑기 + // taskService.findStatus(); + // + // // 로그 저장 + // logService.saveLog(); + // } + + //로그인/로그아웃 +} diff --git a/src/main/java/com/example/onederful/domain/log/controller/.gitkeep b/src/main/java/com/example/onederful/domain/log/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/log/controller/LogController.java b/src/main/java/com/example/onederful/domain/log/controller/LogController.java new file mode 100644 index 0000000..856d877 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/controller/LogController.java @@ -0,0 +1,55 @@ +package com.example.onederful.domain.log.controller; + +import java.time.LocalDate; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.domain.Sort; +import org.springframework.data.repository.query.Param; +import org.springframework.data.web.PageableDefault; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import com.example.onederful.domain.log.dto.LogResponseDto; +import com.example.onederful.domain.log.dto.addLogTestDto; +import com.example.onederful.domain.log.enums.Activity; +import com.example.onederful.domain.log.service.LogService; + +import lombok.RequiredArgsConstructor; + +@RestController +@RequiredArgsConstructor +public class LogController { + + private final LogService logService; + + @PostMapping("/api/activities") + public ResponseEntity addLogTest1() { + return new ResponseEntity<>(logService.addLogTest1(), HttpStatus.OK); + } + + @DeleteMapping("/api/activities/{id}") + public void addLogTest2(@PathVariable Long id) { + logService.addLogTest2(); + } + + @GetMapping("/api/activities") + public ResponseEntity> getLog( + @RequestParam(required = false) Long userId, + @RequestParam(required = false) String activityStr, + @RequestParam(required = false) Long targetId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end, + @PageableDefault(page = 0, size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable + ) { + return new ResponseEntity<>(logService.getLog(userId, activityStr, targetId, start, end, pageable), HttpStatus.OK); + } +} diff --git a/src/main/java/com/example/onederful/domain/log/dto/.gitkeep b/src/main/java/com/example/onederful/domain/log/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java b/src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java new file mode 100644 index 0000000..f738838 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java @@ -0,0 +1,39 @@ +package com.example.onederful.domain.log.dto; + +import java.time.LocalDateTime; + +import com.example.onederful.domain.log.entity.Log; + +import lombok.Getter; + +@Getter +public class LogResponseDto { + LocalDateTime createdAt; + String userName; + String activityStr; + Long targetID; + String logMessage; + + public LogResponseDto( + LocalDateTime createdAt, + String userName, + String activityStr, + Long targetID, + String logMessage) + { + this.createdAt = createdAt; + this.userName = userName; + this.activityStr = activityStr; + this.targetID = targetID; + this.logMessage = logMessage; + } + + public static LogResponseDto of(Log log) { + return new LogResponseDto( + log.getCreatedAt(), + log.getUser().getName(), + log.getActivity().toString(), + log.getTargetId(), + log.getActivity().getLogMessage()); + } +} diff --git a/src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java b/src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java new file mode 100644 index 0000000..8ab6a02 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java @@ -0,0 +1,10 @@ +package com.example.onederful.domain.log.dto; + +import lombok.Getter; + +@Getter +public class addLogTestDto { + Long id; + + public addLogTestDto(Long id) {this.id = id;}; +} diff --git a/src/main/java/com/example/onederful/domain/log/enums/Activity.java b/src/main/java/com/example/onederful/domain/log/enums/Activity.java index abd20e5..376c4f7 100644 --- a/src/main/java/com/example/onederful/domain/log/enums/Activity.java +++ b/src/main/java/com/example/onederful/domain/log/enums/Activity.java @@ -1,6 +1,28 @@ package com.example.onederful.domain.log.enums; public enum Activity { -TASK_CREATED, TASK_UPDATED, TASK_DELETED,TASK_STATUS_CHANGED, COMMENT_CREATED -,COMMENT_UPDATED, COMMENT_DELETED, USER_LOGGED_IN, USER_LOGGED_OUT + // TASK_CREATED, + // TASK_UPDATED, + // TASK_DELETED, + // TASK_STATUS_TODO_TO_IN_PROGRESS, + // TASK_STATUS_IN_PROGRESS_TO_DONE, + // TASK_STATUS_TODO_TO_DONE, + // COMMENT_CREATED, + // COMMENT_UPDATED, + // COMMENT_DELETED, + // USER_LOGGED_IN, + // USER_LOGGED_OUT, + TEST("테스트 입니다."); + + private final String logMessage; + + // 생성자 + Activity(String logMessage) { + this.logMessage = logMessage; + } + + // getter + public String getLogMessage() { + return logMessage; + } } diff --git a/src/main/java/com/example/onederful/domain/log/repository/.gitkeep b/src/main/java/com/example/onederful/domain/log/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/log/repository/LogRepository.java b/src/main/java/com/example/onederful/domain/log/repository/LogRepository.java new file mode 100644 index 0000000..c124625 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/repository/LogRepository.java @@ -0,0 +1,11 @@ +package com.example.onederful.domain.log.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.stereotype.Repository; + +import com.example.onederful.domain.log.entity.Log; + +@Repository +public interface LogRepository extends JpaRepository, JpaSpecificationExecutor { +} diff --git a/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java b/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java new file mode 100644 index 0000000..c5635d9 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java @@ -0,0 +1,41 @@ +package com.example.onederful.domain.log.repository; + +import java.time.LocalDate; + +import org.springframework.data.jpa.domain.Specification; + +import com.example.onederful.domain.log.entity.Log; + +public class LogSpecification { + public static Specification hasUserId(Long userId) { + return (root, query, builder) -> + userId == null ? null : builder.equal(root.get("user").get("id"), userId); + } + + public static Specification hasActivity(String activityStr) { + return (root, query, builder) -> + activityStr == null ? null : builder.equal(root.get("activity"), activityStr); + } + + public static Specification hasTargetId(Long targetId) { + return (root, query, builder) -> + targetId == null ? null : builder.equal(root.get("targetId"), targetId); + } + + public static Specification betweenDates(LocalDate start, LocalDate end) { + return (root, query, builder) -> { + // 둘다 없을 경우 + if (start == null && end == null) return null; + // 둘다 있을 경우 -> between + // start.atStartOfDay() = 00-01-01(시작날) 00:00:00 + // end.plusDays(1).atStartOfDay() = (00-01-02(종료날)일 경우) 00-01-03 00:00:00 + if (start != null && end != null) + return builder.between(root.get("createdAt"), start.atStartOfDay(), end.plusDays(1).atStartOfDay()); + // 시작날만 있을 경우 + if (start != null) + return builder.greaterThanOrEqualTo(root.get("createdAt"), start.atStartOfDay()); + // 종료날만 있을 경우 + return builder.lessThan(root.get("createdAt"), end.plusDays(1).atStartOfDay()); + }; + } +} diff --git a/src/main/java/com/example/onederful/domain/log/service/.gitkeep b/src/main/java/com/example/onederful/domain/log/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java new file mode 100644 index 0000000..27efaa8 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -0,0 +1,106 @@ +package com.example.onederful.domain.log.service; + +import java.time.LocalDate; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; + +import com.example.onederful.domain.log.dto.LogResponseDto; +import com.example.onederful.domain.log.dto.addLogTestDto; +import com.example.onederful.domain.log.entity.Log; +import com.example.onederful.domain.log.enums.Activity; +import com.example.onederful.domain.log.enums.Method; +import com.example.onederful.domain.log.repository.LogRepository; +import com.example.onederful.domain.log.repository.LogSpecification; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.enums.Role; + +import jakarta.transaction.Transactional; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class LogService { + + private final LogRepository logRepository; + private final UserRepository userRepositry; + + public addLogTestDto addLogTest1() { + return new addLogTestDto(1L); + } + + public void addLogTest2() { + } + + public Page getLog( + Long userId, + String activityStr, + Long targetId, + LocalDate start, + LocalDate end, + Pageable pageable) { + + // 들어온 조건 여부로 동적 쿼리 설정 + Specification spec = + LogSpecification.hasUserId(userId) + .and(LogSpecification.hasActivity(activityStr)) + .and(LogSpecification.hasTargetId(targetId)) + .and(LogSpecification.betweenDates(start, end)); + + return logRepository.findAll(spec, pageable) + .map(LogResponseDto::of); + } + + @Transactional + public void saveLog(String ip, Method method, String url, Object result) { + // TODO: 로그인한 정보를 토대로 User 가져오도록 구현 + // 로직 구현용 더미유저 하드 코딩 내용 + User dummyUser = User.builder() + .email("dummy@example.com") + .password("password") + .name("Dummy User") + .role(Role.USER) + .isDeleted(false) + .build(); + userRepositry.save(dummyUser); + //User dummyUser = userRepositry.findById(1L).get(); + + // TODO: 어떤 활동인지, 대상 id 찾기 + // 활동 유형 -> 요청 메서드와 url로 일치하는 활동 유형 찾기 + Activity activity = null; + if (method.equals(Method.POST) && url.contains("/activities")) { + activity = Activity.TEST; + } + else if (method.equals(Method.DELETE) && url.contains("/activities")) { + activity = Activity.TEST; + } + + // 대상 id -> 생성인 경우 응답에서 / 수정과 삭제의 경우 url 마지막에서 찾기 + Long targetId = null; + if (method.equals(Method.POST)) { + if (result instanceof addLogTestDto) { + targetId = ((addLogTestDto) result).getId(); + } + } + else if (method.equals(Method.PATCH) || method.equals(Method.DELETE)) { + String[] parts = url.split("/"); + String lastPart = parts[parts.length - 1]; // /api/.../{id}의 id + targetId = Long.parseLong(lastPart); + } + + // if (activity == null || targetId == null) 예외 처리 + + Log log = Log.builder() + .user(dummyUser) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } +} From 6a14525f7fa23cd1de423070c943e7cce3055d5c Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 16:46:06 +0900 Subject: [PATCH 034/123] =?UTF-8?q?refactor=20:=20DONE=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=20Task=20update=20=EB=A1=9C=EC=A7=81=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20DONE=20process=20=ED=98=95=EC=8B=9D=EC=9D=98=20?= =?UTF-8?q?=EA=B0=92=20=EC=88=98=EC=A0=95=20=EC=8B=9C=20=EB=AC=B4=EC=A1=B0?= =?UTF-8?q?=EA=B1=B4=EC=A0=81=EC=9D=B8=20=EC=97=90=EB=9F=AC=20=EB=B0=9C?= =?UTF-8?q?=EC=83=9D=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/task/service/TaskService.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index e8197ab..166fb97 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -59,9 +59,9 @@ public TaskResponse findTask(Long id) { } @Transactional(readOnly = true) - public Page findTasks(Pageable pageable, String keyword, ProcessStatus status) { + public Page findTasks(Pageable pageable, String search, ProcessStatus status) { - Page tasks = taskRepository.findTasks(keyword, status, pageable); + Page tasks = taskRepository.findTasks(search, status, pageable); return tasks.map(TaskResponse::of); } @@ -81,8 +81,10 @@ public TaskResponse updateTask(Long id, TaskUpdateRequest request) { User assignee = userRepository.findById(request.getAssigneeId()).orElseThrow(); if (task.getStatus() == ProcessStatus.DONE) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "DONE 상태는 이전 상태로 변경 할 수 없습니다."); + if (request.getStatus() != ProcessStatus.DONE) { + throw new ResponseStatusException(HttpStatus.BAD_REQUEST, + "DONE 상태는 이전 상태로 변경 할 수 없습니다."); + } } if (task.getStatus() == ProcessStatus.TODO) { @@ -90,6 +92,7 @@ public TaskResponse updateTask(Long id, TaskUpdateRequest request) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "TODO -> IN_PROCESS으로만 상태 변경이 가능합니다."); } + task.taskStart(); } if (task.getStatus() == ProcessStatus.IN_PROGRESS) { @@ -102,7 +105,7 @@ public TaskResponse updateTask(Long id, TaskUpdateRequest request) { task.updateTask(request.getTitle(), request.getDescription(), request.getPriority(), assignee, request.getDueDate().toLocalDateTime(), request.getStatus()); - + return TaskResponse.of(task); } } From 1baa835af20d7dc0338ecd9b64e62af9a2a84e7a Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 16:46:38 +0900 Subject: [PATCH 035/123] =?UTF-8?q?refactor=20:=20Api=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=EC=97=90=20=EB=A7=9E=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20keyword=20->=20search=20(task=20list=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EB=A1=9C=EC=A7=81)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/task/controller/TaskController.java | 4 ++-- .../java/com/example/onederful/domain/task/entity/Task.java | 4 ++++ .../onederful/domain/task/repository/TaskRepository.java | 4 ++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java index ea4f7a5..e213d15 100644 --- a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -61,12 +61,12 @@ public ResponseEntity> findTask(@PathVariable @NotN public ResponseEntity>> findTasks( @RequestParam(defaultValue = "1") @Min(1) int page, @RequestParam(defaultValue = "5") @Min(5) int size, - @RequestParam(defaultValue = "") String keyword, + @RequestParam(defaultValue = "") String search, @RequestParam(defaultValue = "TODO") ProcessStatus status ) { Pageable pageable = PageRequest.of(page - 1, size, Direction.ASC, "dueDate"); - Page response = taskService.findTasks(pageable, keyword, + Page response = taskService.findTasks(pageable, search, status); return ResponseEntity.ok( diff --git a/src/main/java/com/example/onederful/domain/task/entity/Task.java b/src/main/java/com/example/onederful/domain/task/entity/Task.java index 7cf5a20..f8efa3e 100644 --- a/src/main/java/com/example/onederful/domain/task/entity/Task.java +++ b/src/main/java/com/example/onederful/domain/task/entity/Task.java @@ -98,4 +98,8 @@ public void delete() { this.isDeleted = true; this.deletedAt = LocalDateTime.now(); } + + public void taskStart() { + this.startedAt = LocalDateTime.now(); + } } diff --git a/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java b/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java index 8044466..c2bd7a8 100644 --- a/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java +++ b/src/main/java/com/example/onederful/domain/task/repository/TaskRepository.java @@ -12,7 +12,7 @@ @Repository public interface TaskRepository extends JpaRepository { - @Query("SELECT t FROM Task t WHERE (t.title LIKE %:keyword% OR t.description LIKE %:keyword%) AND t.status = :status") - Page findTasks(@Param("keyword") String keyword, @Param("status") ProcessStatus status, + @Query("SELECT t FROM Task t WHERE (t.title LIKE %:search% OR t.description LIKE %:search%) AND t.status = :status") + Page findTasks(@Param("search") String search, @Param("status") ProcessStatus status, Pageable pageable); } From 9330dab2771bd21bd27b1555be93b2d2fabc9d94 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Mon, 16 Jun 2025 17:55:22 +0900 Subject: [PATCH 036/123] =?UTF-8?q?feat:=20comment=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(=EC=88=98=EC=A0=95?= =?UTF-8?q?=ED=95=84=EC=9A=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + .../comment/controller/CommentController.java | 36 +++++++++++++++++++ .../comment/dto/CreateCommentRequestDto.java | 14 ++++++++ .../dto/CreateCommentResponseDataDto.java | 18 ++++++++++ .../domain/comment/dto/ResponseDto.java | 28 +++++++++++++++ .../domain/comment/entity/Comment.java | 12 +++++-- .../comment/repository/CommentRepository.java | 7 ++++ .../comment/service/CommentService.java | 28 +++++++++++++++ 8 files changed, 142 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/comment/controller/CommentController.java create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java create mode 100644 src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java create mode 100644 src/main/java/com/example/onederful/domain/comment/service/CommentService.java diff --git a/build.gradle b/build.gradle index 22f4c2e..8396949 100644 --- a/build.gradle +++ b/build.gradle @@ -27,6 +27,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' + implementation 'org.springframework.boot:spring-boot-starter-security' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java new file mode 100644 index 0000000..b1650f0 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -0,0 +1,36 @@ +package com.example.onederful.domain.comment.controller; + +import com.example.onederful.domain.comment.dto.CreateCommentRequestDto; +import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; +import com.example.onederful.domain.comment.dto.ResponseDto; +import com.example.onederful.domain.comment.service.CommentService; +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; + +@RestController +@RequestMapping("/api/comments") +@RequiredArgsConstructor +public class CommentController { + + private final CommentService commentService; + + @PostMapping + //public ResponseEntity save (@AuthenticationPrincipal AuthUser authUser, @RequestBody CreateCommentRequestDto requestDto){ + public ResponseEntity> save( + String username, @RequestBody CreateCommentRequestDto requestDto) { +// Long userId = authUser.getUserId(); +// User user = userRepository.findById(userId) +// .orElseThrow(() -> new IllegalArgumentException("User not found")); + username = "홍길동"; + + CreateCommentResponseDataDto createCommentResponseDataDto = + commentService.save(username, requestDto.getContents()); + ResponseDto responseDto = ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto); + + return ResponseEntity.ok(responseDto); + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java new file mode 100644 index 0000000..33258bb --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java @@ -0,0 +1,14 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; + +@Getter +public class CreateCommentRequestDto { + + private final String contents; + + public CreateCommentRequestDto(String writer, String contents) { + this.contents = contents; + } + +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java new file mode 100644 index 0000000..4a19895 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java @@ -0,0 +1,18 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; + +@Getter +public class CreateCommentResponseDataDto { + + private final Long id; + private final String writer; + private final String contents; + + public CreateCommentResponseDataDto(Long id, String writer, String contents){ + this.id = id; + this.writer = writer; + this.contents = contents; + } + +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java b/src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java new file mode 100644 index 0000000..f9e81cc --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java @@ -0,0 +1,28 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; + +import java.time.OffsetDateTime; + +@Getter +public class ResponseDto { + private final boolean success; + private final String message; + private final T dataDto; + private final OffsetDateTime timestamp; + + public ResponseDto(boolean success, String message, T dataDto) { + this.success = success; + this.message = message; + this.dataDto = dataDto; + this.timestamp = OffsetDateTime.now(); + } + + public static ResponseDto success(String message, T data){ + return new ResponseDto<>(true, message, data); + } + + public static ResponseDto fail(String message){ + return new ResponseDto<>(false, message, null); + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java index 3eb7610..179fd4c 100644 --- a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java +++ b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java @@ -19,6 +19,8 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.Comments; +import org.springframework.cglib.core.Local; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -36,8 +38,8 @@ public class Comment { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name = "content", nullable = false) - private String content; + @Column(name = "contents", nullable = false) + private String contents; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name= "task_id", nullable = false) @@ -62,4 +64,10 @@ public class Comment { @Column(name="is_deleted", nullable = false) private Boolean isDeleted = false; + public Comment(String contents, User user){ + this.user = user; + this.contents = contents; + this.createdAt = LocalDateTime.now(); + } + } diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java new file mode 100644 index 0000000..d134d72 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -0,0 +1,7 @@ +package com.example.onederful.domain.comment.repository; + +import com.example.onederful.domain.comment.entity.Comment; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface CommentRepository extends JpaRepository { +} diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java new file mode 100644 index 0000000..dc88229 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -0,0 +1,28 @@ +package com.example.onederful.domain.comment.service; + +import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; +import com.example.onederful.domain.comment.dto.ResponseDto; +import com.example.onederful.domain.comment.entity.Comment; +import com.example.onederful.domain.comment.repository.CommentRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class CommentService { + + private final CommentRepository commentRepository; + private final UserRepository userRepository; + + public CreateCommentResponseDataDto save(String username, String contents){ + + User user = userRepository.findById(authUser.getUserId()) + .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + + Comment comment = new Comment(contents, user); + Comment savedComment = commentRepository.save(comment); + + return new CreateCommentResponseDataDto(savedComment.getId(), "홍길동", savedComment.getContents()); + + } +} From 80b68c2c236f1f165c6eacc41552e77070a6a02f Mon Sep 17 00:00:00 2001 From: doohaaa Date: Mon, 16 Jun 2025 21:13:43 +0900 Subject: [PATCH 037/123] =?UTF-8?q?feat:=20comment=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84=20(=EC=88=98=EC=A0=95?= =?UTF-8?q?=20=ED=95=84=EC=9A=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 25 +++++++++++++------ .../comment/dto/CommentResponseDataDto.java | 24 ++++++++++++++++++ .../comment/dto/UpdateCommentRequestDto.java | 13 ++++++++++ .../dto/UpdateCommentResponseDataDto.java | 25 +++++++++++++++++++ .../domain/comment/entity/Comment.java | 5 ++++ .../comment/service/CommentService.java | 18 +++++++++++-- 6 files changed, 101 insertions(+), 9 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index b1650f0..9bb69ab 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -1,15 +1,13 @@ package com.example.onederful.domain.comment.controller; -import com.example.onederful.domain.comment.dto.CreateCommentRequestDto; -import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; -import com.example.onederful.domain.comment.dto.ResponseDto; +import com.example.onederful.domain.comment.dto.*; import com.example.onederful.domain.comment.service.CommentService; 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.springframework.security.core.annotation.AuthenticationPrincipal; +import org.springframework.web.bind.annotation.*; + +import java.util.List; @RestController @RequestMapping("/api/comments") @@ -18,6 +16,7 @@ public class CommentController { private final CommentService commentService; + // 댓글 생성 @PostMapping //public ResponseEntity save (@AuthenticationPrincipal AuthUser authUser, @RequestBody CreateCommentRequestDto requestDto){ public ResponseEntity> save( @@ -33,4 +32,16 @@ public ResponseEntity> save( return ResponseEntity.ok(responseDto); } + + // 댓글 수정 + @PatchMapping("/{comment_id}") + public ResponseEntity> updateComment( + @PathVariable Long id, @RequestBody UpdateCommentRequestDto requestDto, @AuthenticationPrincipal AuthUser authUser + ){ + Long userId = authUser.getUserId(); + UpdateCommentResponseDataDto updateCommentResponseDataDto = + commentService.updateComment(id, requestDto.getContents(), userId); + return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); + } + } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java new file mode 100644 index 0000000..a37a1bd --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java @@ -0,0 +1,24 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +@Getter +public class CommentResponseDataDto { + private final Long taskId; + private final String writer; + private final String contents; + private final LocalDateTime createdAt; + private final LocalDateTime updatedAt; + + + public CommentResponseDataDto(Long taskId, String writer, String contents, LocalDateTime createdAt, LocalDateTime updatedAt) { + this.taskId = taskId; + this.writer = writer; + this.contents = contents; + this.createdAt = createdAt; + this.updatedAt = updatedAt; + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java new file mode 100644 index 0000000..ff9ca54 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java @@ -0,0 +1,13 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; + +@Getter +public class UpdateCommentRequestDto { + + private final String contents; + + public UpdateCommentRequestDto(String contents){ + this.contents = contents; + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java new file mode 100644 index 0000000..8fa80d8 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java @@ -0,0 +1,25 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; +import org.springframework.cglib.core.Local; + +import java.time.LocalDateTime; + +@Getter +public class UpdateCommentResponseDataDto { + + private final Long id; + private final String writer; + private final String contents; + private final LocalDateTime created_at; + private final LocalDateTime updated_at; + + + public UpdateCommentResponseDataDto(Long id, String writer, String contents, LocalDateTime createdAt, LocalDateTime updatedAt) { + this.id = id; + this.writer = writer; + this.contents = contents; + this.created_at = createdAt; + this.updated_at = updatedAt; + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java index 179fd4c..ddab327 100644 --- a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java +++ b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java @@ -70,4 +70,9 @@ public Comment(String contents, User user){ this.createdAt = LocalDateTime.now(); } + public void update(String contents){ + this.contents = contents; + this.updatedAt = LocalDateTime.now(); + } + } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index dc88229..d033647 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -2,10 +2,12 @@ import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; import com.example.onederful.domain.comment.dto.ResponseDto; +import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -14,10 +16,10 @@ public class CommentService { private final CommentRepository commentRepository; private final UserRepository userRepository; - public CreateCommentResponseDataDto save(String username, String contents){ + public CreateCommentResponseDataDto save(String username, String contents) { User user = userRepository.findById(authUser.getUserId()) - .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); Comment comment = new Comment(contents, user); Comment savedComment = commentRepository.save(comment); @@ -25,4 +27,16 @@ public CreateCommentResponseDataDto save(String username, String contents){ return new CreateCommentResponseDataDto(savedComment.getId(), "홍길동", savedComment.getContents()); } + + @Transactional + public UpdateCommentResponseDataDto updateComment(Long commentId, String contents, Long userId) { + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() ->new IllegalArgumentException("댓글을 찾을 수 없습니다.")); + + User user = userRepository.findById(userId) + .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + + comment.update(contents); + return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContents(),comment.getCreatedAt(), comment.getUpdatedAt()); + } } From ad7db4cf9c8650cc39886756e49a82ae6d5f86ea Mon Sep 17 00:00:00 2001 From: doohaaa Date: Mon, 16 Jun 2025 21:59:14 +0900 Subject: [PATCH 038/123] =?UTF-8?q?feat:=20=EA=B0=81=20task=EC=97=90=20?= =?UTF-8?q?=EB=8B=AC=EB=A6=B0=20comment=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 9 ++++++++- .../domain/comment/dto/CommentResponseDataDto.java | 14 +++++++++++--- .../comment/repository/CommentRepository.java | 4 ++++ .../domain/comment/service/CommentService.java | 12 ++++++++++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 9bb69ab..76a621a 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -37,11 +37,18 @@ public ResponseEntity> save( @PatchMapping("/{comment_id}") public ResponseEntity> updateComment( @PathVariable Long id, @RequestBody UpdateCommentRequestDto requestDto, @AuthenticationPrincipal AuthUser authUser - ){ + ) { Long userId = authUser.getUserId(); UpdateCommentResponseDataDto updateCommentResponseDataDto = commentService.updateComment(id, requestDto.getContents(), userId); return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); } + // 테스크별 댓글 조회 + @GetMapping("/task/{task_id}") + public ResponseEntity>> findAllCommentByTaskId( + @PathVariable Long taskId) { + List commentResponseDataDtoList = commentService.findAllCommentByTaskId(taskId); + return ResponseEntity.ok(ResponseDto.success("데스크 " + taskId + "에 달린 댓글 목록", commentResponseDataDtoList)); + } } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java index a37a1bd..ff1d62c 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java @@ -1,5 +1,6 @@ package com.example.onederful.domain.comment.dto; +import com.example.onederful.domain.comment.entity.Comment; import lombok.Getter; import java.time.LocalDate; @@ -7,18 +8,25 @@ @Getter public class CommentResponseDataDto { - private final Long taskId; private final String writer; private final String contents; private final LocalDateTime createdAt; private final LocalDateTime updatedAt; - public CommentResponseDataDto(Long taskId, String writer, String contents, LocalDateTime createdAt, LocalDateTime updatedAt) { - this.taskId = taskId; + public CommentResponseDataDto(String writer, String contents, LocalDateTime createdAt, LocalDateTime updatedAt) { this.writer = writer; this.contents = contents; this.createdAt = createdAt; this.updatedAt = updatedAt; } + + public static CommentResponseDataDto from(Comment comment){ + return new CommentResponseDataDto( + comment.getUser().getName(), + comment.getContents(), + comment.getCreatedAt(), + comment.getUpdatedAt() + ); + } } diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java index d134d72..9886dad 100644 --- a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -3,5 +3,9 @@ import com.example.onederful.domain.comment.entity.Comment; import org.springframework.data.jpa.repository.JpaRepository; +import java.util.List; + public interface CommentRepository extends JpaRepository { + + List findAllByTaskIdOrderByCreatedAtDesc(Long taskId); } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index d033647..e4280dd 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -1,5 +1,6 @@ package com.example.onederful.domain.comment.service; +import com.example.onederful.domain.comment.dto.CommentResponseDataDto; import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; import com.example.onederful.domain.comment.dto.ResponseDto; import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; @@ -9,6 +10,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.List; +import java.util.stream.Collectors; + @Service @RequiredArgsConstructor public class CommentService { @@ -39,4 +43,12 @@ public UpdateCommentResponseDataDto updateComment(Long commentId, String content comment.update(contents); return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContents(),comment.getCreatedAt(), comment.getUpdatedAt()); } + + public List findAllCommentByTaskId(Long taskId){ + List commentList = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(taskId); + + return commentList.stream() + .map(CommentResponseDataDto::from) + .collect(Collectors.toList()); + } } From 7327b5f3d2a7fa539122e201b81ab8fbfccfc870 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 09:45:20 +0900 Subject: [PATCH 039/123] =?UTF-8?q?feat:=20=EB=8C=93=EA=B8=80=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/controller/CommentController.java | 9 +++++++++ .../example/onederful/domain/comment/entity/Comment.java | 5 +++++ .../onederful/domain/comment/service/CommentService.java | 8 ++++++++ 3 files changed, 22 insertions(+) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 76a621a..c3c68d7 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -3,6 +3,7 @@ import com.example.onederful.domain.comment.dto.*; import com.example.onederful.domain.comment.service.CommentService; 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.*; @@ -51,4 +52,12 @@ public ResponseEntity>> findAllCommentB List commentResponseDataDtoList = commentService.findAllCommentByTaskId(taskId); return ResponseEntity.ok(ResponseDto.success("데스크 " + taskId + "에 달린 댓글 목록", commentResponseDataDtoList)); } + + // 댓글 삭제 + @DeleteMapping("/{comment_id}") + public ResponseEntity> deleteComment(@PathVariable Long commentId){ + commentService.deleteComment(commentId); + return ResponseEntity.ok(ResponseDto.success("댓글이 삭제되었습니다.", null)); + } + } diff --git a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java index ddab327..411d849 100644 --- a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java +++ b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java @@ -75,4 +75,9 @@ public void update(String contents){ this.updatedAt = LocalDateTime.now(); } + public void delete(){ + this.isDeleted = true; + this.deletedAt= LocalDateTime.now(); + } + } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index e4280dd..885e476 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -51,4 +51,12 @@ public List findAllCommentByTaskId(Long taskId){ .map(CommentResponseDataDto::from) .collect(Collectors.toList()); } + + @Transactional + public void deleteComment(Long commentId){ + Comment comment = commentRepository.findById(commentId) + .orElseThrow(() ->new IllegalArgumentException("댓글을 찾을 수 없습니다.")); + + comment.delete(); + } } From 0c202944356a593448caebd5b60555b35d70276c Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 09:58:19 +0900 Subject: [PATCH 040/123] =?UTF-8?q?fix:=20=EC=82=AD=EC=A0=9C=EB=90=9C=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=A1=B0=ED=9A=8C=EB=A5=BC=20=EB=A7=89?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/comment/service/CommentService.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 885e476..81d0ed0 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -40,6 +40,10 @@ public UpdateCommentResponseDataDto updateComment(Long commentId, String content User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + if(comment.getIsDeleted()==true){ + throw new IllegalArgumentException("삭제된 댓글입니다."); + } + comment.update(contents); return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContents(),comment.getCreatedAt(), comment.getUpdatedAt()); } From 68cbe70e065fe945428278dede513f6601b3ffab Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 12:23:36 +0900 Subject: [PATCH 041/123] =?UTF-8?q?feat:=20=EB=82=B4=EC=9A=A9=EC=9D=84=20?= =?UTF-8?q?=ED=8F=AC=ED=95=A8=ED=95=98=EB=8A=94=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 20 ++++++++++++++----- .../comment/repository/CommentRepository.java | 2 ++ .../comment/service/CommentService.java | 16 +++++++++++++-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index c3c68d7..5c92396 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -11,14 +11,14 @@ import java.util.List; @RestController -@RequestMapping("/api/comments") +@RequestMapping("/api") @RequiredArgsConstructor public class CommentController { private final CommentService commentService; // 댓글 생성 - @PostMapping + @PostMapping("/comments") //public ResponseEntity save (@AuthenticationPrincipal AuthUser authUser, @RequestBody CreateCommentRequestDto requestDto){ public ResponseEntity> save( String username, @RequestBody CreateCommentRequestDto requestDto) { @@ -35,7 +35,7 @@ public ResponseEntity> save( } // 댓글 수정 - @PatchMapping("/{comment_id}") + @PatchMapping("/comments/{comment_id}") public ResponseEntity> updateComment( @PathVariable Long id, @RequestBody UpdateCommentRequestDto requestDto, @AuthenticationPrincipal AuthUser authUser ) { @@ -46,15 +46,25 @@ public ResponseEntity> updateComment( } // 테스크별 댓글 조회 - @GetMapping("/task/{task_id}") + @GetMapping("/comments/task/{task_id}") public ResponseEntity>> findAllCommentByTaskId( @PathVariable Long taskId) { List commentResponseDataDtoList = commentService.findAllCommentByTaskId(taskId); return ResponseEntity.ok(ResponseDto.success("데스크 " + taskId + "에 달린 댓글 목록", commentResponseDataDtoList)); } + // 내용으로 댓글 조회 + @GetMapping("/search") + public ResponseEntity> findCommentByContents(@RequestBody String contents){ + List commentResponseDataDtoList = commentService.findCommentByContents(contents); + return ResponseEntity.ok(ResponseDto.success( contents + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); + } + + + + // 댓글 삭제 - @DeleteMapping("/{comment_id}") + @DeleteMapping("/comments/{comment_id}") public ResponseEntity> deleteComment(@PathVariable Long commentId){ commentService.deleteComment(commentId); return ResponseEntity.ok(ResponseDto.success("댓글이 삭제되었습니다.", null)); diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java index 9886dad..e13b4f9 100644 --- a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -8,4 +8,6 @@ public interface CommentRepository extends JpaRepository { List findAllByTaskIdOrderByCreatedAtDesc(Long taskId); + + List findByNameLike(String contents); } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 81d0ed0..24fe7a8 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -49,13 +49,25 @@ public UpdateCommentResponseDataDto updateComment(Long commentId, String content } public List findAllCommentByTaskId(Long taskId){ - List commentList = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(taskId); + List commentListById = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(taskId); - return commentList.stream() + return commentListById.stream() .map(CommentResponseDataDto::from) .collect(Collectors.toList()); } + + public List findCommentByContents(String contents){ + + List commentListByContents = commentRepository.findByNameLike("%"+contents+"%"); + + return commentListByContents.stream() + .filter(comment -> !comment.getIsDeleted()) + .map(CommentResponseDataDto::from) + .collect(Collectors.toList()); + } + + @Transactional public void deleteComment(Long commentId){ Comment comment = commentRepository.findById(commentId) From 09b2f576116071cbc7cc1b4434de73b33b8dcf5d Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 16:14:03 +0900 Subject: [PATCH 042/123] =?UTF-8?q?fix:=20=EC=82=AD=EC=A0=9C=EB=90=9C=20?= =?UTF-8?q?=EB=8C=93=EA=B8=80=20=EC=A1=B0=ED=9A=8C=EB=A5=BC=20=EB=A7=89?= =?UTF-8?q?=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EC=B6=94=EA=B0=80,=20?= =?UTF-8?q?=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/comment/controller/CommentController.java | 2 +- .../onederful/domain/comment/service/CommentService.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 5c92396..5de71c1 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -55,7 +55,7 @@ public ResponseEntity>> findAllCommentB // 내용으로 댓글 조회 @GetMapping("/search") - public ResponseEntity> findCommentByContents(@RequestBody String contents){ + public ResponseEntity>> findCommentByContents(@RequestBody String contents){ List commentResponseDataDtoList = commentService.findCommentByContents(contents); return ResponseEntity.ok(ResponseDto.success( contents + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 24fe7a8..22275f6 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -52,6 +52,7 @@ public List findAllCommentByTaskId(Long taskId){ List commentListById = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(taskId); return commentListById.stream() + .filter(comment -> !comment.getIsDeleted()) .map(CommentResponseDataDto::from) .collect(Collectors.toList()); } From 6f00c2b3628f885c188ac2532b4758ecd1c96e5f Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 19:40:55 +0900 Subject: [PATCH 043/123] =?UTF-8?q?refactor:=20userId=20=EB=B0=9B=EC=95=84?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95,?= =?UTF-8?q?=20security=20=EC=9D=98=EC=A1=B4=EC=84=B1=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 2 +- .../comment/controller/CommentController.java | 23 ++++++++----------- .../comment/repository/CommentRepository.java | 2 +- .../comment/service/CommentService.java | 10 ++++---- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/build.gradle b/build.gradle index 8396949..4d3cc50 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,7 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' - implementation 'org.springframework.boot:spring-boot-starter-security' + //implementation 'org.springframework.boot:spring-boot-starter-security' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 5de71c1..9b39043 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -2,6 +2,8 @@ import com.example.onederful.domain.comment.dto.*; import com.example.onederful.domain.comment.service.CommentService; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; @@ -16,19 +18,15 @@ public class CommentController { private final CommentService commentService; + private final UserRepository userRepository; // 댓글 생성 @PostMapping("/comments") - //public ResponseEntity save (@AuthenticationPrincipal AuthUser authUser, @RequestBody CreateCommentRequestDto requestDto){ - public ResponseEntity> save( - String username, @RequestBody CreateCommentRequestDto requestDto) { -// Long userId = authUser.getUserId(); -// User user = userRepository.findById(userId) -// .orElseThrow(() -> new IllegalArgumentException("User not found")); - username = "홍길동"; + + public ResponseEntity> save (@AuthenticationPrincipal Long userId, @RequestBody CreateCommentRequestDto requestDto){ CreateCommentResponseDataDto createCommentResponseDataDto = - commentService.save(username, requestDto.getContents()); + commentService.save(userId, requestDto.getContents()); ResponseDto responseDto = ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto); return ResponseEntity.ok(responseDto); @@ -37,11 +35,10 @@ public ResponseEntity> save( // 댓글 수정 @PatchMapping("/comments/{comment_id}") public ResponseEntity> updateComment( - @PathVariable Long id, @RequestBody UpdateCommentRequestDto requestDto, @AuthenticationPrincipal AuthUser authUser + @PathVariable Long commentId, @RequestBody UpdateCommentRequestDto requestDto, @AuthenticationPrincipal Long userId ) { - Long userId = authUser.getUserId(); UpdateCommentResponseDataDto updateCommentResponseDataDto = - commentService.updateComment(id, requestDto.getContents(), userId); + commentService.updateComment(commentId, requestDto.getContents(), userId); return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); } @@ -50,7 +47,7 @@ public ResponseEntity> updateComment( public ResponseEntity>> findAllCommentByTaskId( @PathVariable Long taskId) { List commentResponseDataDtoList = commentService.findAllCommentByTaskId(taskId); - return ResponseEntity.ok(ResponseDto.success("데스크 " + taskId + "에 달린 댓글 목록", commentResponseDataDtoList)); + return ResponseEntity.ok(ResponseDto.success("task " + taskId + "에 달린 댓글 목록", commentResponseDataDtoList)); } // 내용으로 댓글 조회 @@ -61,8 +58,6 @@ public ResponseEntity>> findCommentByCo } - - // 댓글 삭제 @DeleteMapping("/comments/{comment_id}") public ResponseEntity> deleteComment(@PathVariable Long commentId){ diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java index e13b4f9..d51bdb4 100644 --- a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -9,5 +9,5 @@ public interface CommentRepository extends JpaRepository { List findAllByTaskIdOrderByCreatedAtDesc(Long taskId); - List findByNameLike(String contents); + List findByContentsLike(String contents); } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 22275f6..a226f28 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -6,6 +6,8 @@ import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.repository.UserRepository; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -20,15 +22,15 @@ public class CommentService { private final CommentRepository commentRepository; private final UserRepository userRepository; - public CreateCommentResponseDataDto save(String username, String contents) { + public CreateCommentResponseDataDto save(Long userId, String contents) { - User user = userRepository.findById(authUser.getUserId()) + User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); Comment comment = new Comment(contents, user); Comment savedComment = commentRepository.save(comment); - return new CreateCommentResponseDataDto(savedComment.getId(), "홍길동", savedComment.getContents()); + return new CreateCommentResponseDataDto(savedComment.getId(), user.getName(), savedComment.getContents()); } @@ -60,7 +62,7 @@ public List findAllCommentByTaskId(Long taskId){ public List findCommentByContents(String contents){ - List commentListByContents = commentRepository.findByNameLike("%"+contents+"%"); + List commentListByContents = commentRepository.findByContentsLike("%"+contents+"%"); return commentListByContents.stream() .filter(comment -> !comment.getIsDeleted()) From cb291a1d38fbc2535ab2b45d23bed885787a2c26 Mon Sep 17 00:00:00 2001 From: saevit Date: Tue, 17 Jun 2025 19:46:17 +0900 Subject: [PATCH 044/123] =?UTF-8?q?refactor:=20HttpRequestInfo=20=EA=B0=80?= =?UTF-8?q?=EC=A0=B8=EC=98=A4=EB=8A=94=20=EB=A1=9C=EC=A7=81=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/HttpRequestUtil.java | 59 +++++++++++++++++++ .../onederful/domain/log/LoggingAspect.java | 19 +++--- .../domain/log/controller/LogController.java | 4 +- .../onederful/domain/log/enums/Activity.java | 4 +- .../log/repository/LogSpecification.java | 5 +- .../domain/log/service/LogService.java | 33 ++++------- 6 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java diff --git a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java new file mode 100644 index 0000000..567fbc2 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java @@ -0,0 +1,59 @@ +package com.example.onederful.domain.log; + +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import com.example.onederful.domain.log.enums.Method; +import com.example.onederful.security.JwtUtil; + +import jakarta.servlet.http.HttpServletRequest; +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Component +@RequiredArgsConstructor +public class HttpRequestUtil { + + private final JwtUtil jwtUtil; + + // HttpServletRequest으로부터 요청 ip, 메서드, url, userId + public RequestInfo getRequestInfo() { + ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attrs == null) { + throw new IllegalStateException("Request attributes not found"); + } + HttpServletRequest request = attrs.getRequest(); + if (request == null) { + throw new IllegalStateException("HttpServletRequest not found"); + } + + // 요청한 사용자의 ip + String ip = request.getRemoteAddr(); + + // 요청 메서드 + String method = request.getMethod(); + Method enumMethod = Method.valueOf(method); + + // 요청 url + String url = request.getRequestURI(); + + // 요청 헤더의 토큰으로부터 요청한 사용자의 userId + String authorizationHeader = request.getHeader("Authorization"); + String token = authorizationHeader.substring(7); + Long userId = jwtUtil.extractId(token); + + return new RequestInfo(ip, enumMethod, url, userId); + } + + // 반환용 클래스 + @Getter + @AllArgsConstructor + public static class RequestInfo { + private final String ip; + private final Method method; + private final String url; + private final Long userId; + } +} diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index 5b666d9..894dcaa 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -19,29 +19,25 @@ @RequiredArgsConstructor public class LoggingAspect { + private final HttpRequestUtil httpRequestUtil; private final LogService logService; @Pointcut("execution(* com.example..LogService.addLogTest1()) || execution(* com.example..LogService.addLogTest2())") public void serviceMethods() {} + @Pointcut("execution(* com.example..userService.login())") + public void loginMethods() {} + // 생성, 수정, 삭제 @AfterReturning(pointcut = "serviceMethods()", returning = "result") public void logAfterReturning(JoinPoint joinPoint, Object result) { System.out.println("메서드 정상 실행 후: 로그 기록"); // HttpServletRequest으로부터 요청 ip, 메서드, url - HttpServletRequest request = - ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest(); - - // if (request == null) 예외 처리 - - String ip = request.getRemoteAddr(); - String method = request.getMethod(); - Method enumMethod = Method.valueOf(method); - String url = request.getRequestURI(); + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); // 로그 저장 - logService.saveLog(ip, enumMethod, url, result); + logService.saveLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), result); } // 상태 변경 @@ -59,5 +55,6 @@ public void logAfterReturning(JoinPoint joinPoint, Object result) { // logService.saveLog(); // } - //로그인/로그아웃 + // 로그인/로그아웃 + } diff --git a/src/main/java/com/example/onederful/domain/log/controller/LogController.java b/src/main/java/com/example/onederful/domain/log/controller/LogController.java index 856d877..f47ae09 100644 --- a/src/main/java/com/example/onederful/domain/log/controller/LogController.java +++ b/src/main/java/com/example/onederful/domain/log/controller/LogController.java @@ -44,12 +44,12 @@ public void addLogTest2(@PathVariable Long id) { @GetMapping("/api/activities") public ResponseEntity> getLog( @RequestParam(required = false) Long userId, - @RequestParam(required = false) String activityStr, + @RequestParam(required = false) String activity, @RequestParam(required = false) Long targetId, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start, @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end, @PageableDefault(page = 0, size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable ) { - return new ResponseEntity<>(logService.getLog(userId, activityStr, targetId, start, end, pageable), HttpStatus.OK); + return new ResponseEntity<>(logService.getLog(userId, activity, targetId, start, end, pageable), HttpStatus.OK); } } diff --git a/src/main/java/com/example/onederful/domain/log/enums/Activity.java b/src/main/java/com/example/onederful/domain/log/enums/Activity.java index 376c4f7..7bf57d2 100644 --- a/src/main/java/com/example/onederful/domain/log/enums/Activity.java +++ b/src/main/java/com/example/onederful/domain/log/enums/Activity.java @@ -10,8 +10,8 @@ public enum Activity { // COMMENT_CREATED, // COMMENT_UPDATED, // COMMENT_DELETED, - // USER_LOGGED_IN, - // USER_LOGGED_OUT, + USER_LOGGED_IN("로그인 하였습니다."), + USER_LOGGED_OUT("로그아웃 하였습니다."), TEST("테스트 입니다."); private final String logMessage; diff --git a/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java b/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java index c5635d9..e08c42d 100644 --- a/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java +++ b/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java @@ -5,6 +5,7 @@ import org.springframework.data.jpa.domain.Specification; import com.example.onederful.domain.log.entity.Log; +import com.example.onederful.domain.log.enums.Activity; public class LogSpecification { public static Specification hasUserId(Long userId) { @@ -12,9 +13,9 @@ public static Specification hasUserId(Long userId) { userId == null ? null : builder.equal(root.get("user").get("id"), userId); } - public static Specification hasActivity(String activityStr) { + public static Specification hasActivity(Activity activity) { return (root, query, builder) -> - activityStr == null ? null : builder.equal(root.get("activity"), activityStr); + activity == null ? null : builder.equal(root.get("activity"), activity); } public static Specification hasTargetId(Long targetId) { diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index 27efaa8..687d12f 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -16,6 +16,9 @@ import com.example.onederful.domain.log.repository.LogSpecification; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.enums.Role; +import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.exception.CustomException; +import com.example.onederful.exception.ErrorCode; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -35,17 +38,14 @@ public void addLogTest2() { } public Page getLog( - Long userId, - String activityStr, - Long targetId, - LocalDate start, - LocalDate end, - Pageable pageable) { + Long userId, String activityStr, Long targetId, + LocalDate start, LocalDate end, Pageable pageable) { // 들어온 조건 여부로 동적 쿼리 설정 + Activity activity = (activityStr != null) ? Activity.valueOf(activityStr) : null; Specification spec = LogSpecification.hasUserId(userId) - .and(LogSpecification.hasActivity(activityStr)) + .and(LogSpecification.hasActivity(activity)) .and(LogSpecification.hasTargetId(targetId)) .and(LogSpecification.betweenDates(start, end)); @@ -54,18 +54,11 @@ public Page getLog( } @Transactional - public void saveLog(String ip, Method method, String url, Object result) { - // TODO: 로그인한 정보를 토대로 User 가져오도록 구현 - // 로직 구현용 더미유저 하드 코딩 내용 - User dummyUser = User.builder() - .email("dummy@example.com") - .password("password") - .name("Dummy User") - .role(Role.USER) - .isDeleted(false) - .build(); - userRepositry.save(dummyUser); - //User dummyUser = userRepositry.findById(1L).get(); + public void saveLog(String ip, Method method, String url, Long userId, Object result) { + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); // TODO: 어떤 활동인지, 대상 id 찾기 // 활동 유형 -> 요청 메서드와 url로 일치하는 활동 유형 찾기 @@ -93,7 +86,7 @@ else if (method.equals(Method.PATCH) || method.equals(Method.DELETE)) { // if (activity == null || targetId == null) 예외 처리 Log log = Log.builder() - .user(dummyUser) + .user(user) .activity(activity) .ipAddress(ip) .method(method) From d60c0be8d04266945661a8ea9083ead6152d507b Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 20:13:38 +0900 Subject: [PATCH 045/123] =?UTF-8?q?feat=20:=20Swagger=20=EC=9D=98=EC=A1=B4?= =?UTF-8?q?=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 63 +++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/build.gradle b/build.gradle index 22f4c2e..4140040 100644 --- a/build.gradle +++ b/build.gradle @@ -1,50 +1,53 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.5.0' - id 'io.spring.dependency-management' version '1.1.7' + id 'java' + id 'org.springframework.boot' version '3.5.0' + id 'io.spring.dependency-management' version '1.1.7' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - // JWT - implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' - runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' - runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' - - // bcrypt - implementation 'at.favre.lib:bcrypt:0.10.2' - - // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // JWT + implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' + + // bcrypt + implementation 'at.favre.lib:bcrypt:0.10.2' + + // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' + + // Swagger + implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.8.6' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } From 69dac55150f63c3217a83088a59951ec0f25a747 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 20:14:04 +0900 Subject: [PATCH 046/123] =?UTF-8?q?feat=20:=20Swagger=20Config=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9E=91=EC=84=B1=20Jwt=20Token=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EB=A1=9C=EC=A7=81=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 --- .../onederful/config/SwaggerConfig.java | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 src/main/java/com/example/onederful/config/SwaggerConfig.java diff --git a/src/main/java/com/example/onederful/config/SwaggerConfig.java b/src/main/java/com/example/onederful/config/SwaggerConfig.java new file mode 100644 index 0000000..08575de --- /dev/null +++ b/src/main/java/com/example/onederful/config/SwaggerConfig.java @@ -0,0 +1,27 @@ +package com.example.onederful.config; + +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SwaggerConfig { + + @Bean + public OpenAPI openAPI() { + SecurityScheme bearerAuth = new SecurityScheme() + .type(SecurityScheme.Type.HTTP) + .scheme("bearer") + .bearerFormat("JWT"); + + SecurityRequirement securityRequirement = new SecurityRequirement() + .addList("BearerAuth"); + + return new OpenAPI() + .components(new Components().addSecuritySchemes("BearerAuth", bearerAuth)) + .addSecurityItem(securityRequirement); + } +} From 2c81d889d3bfc3bec1c631031e0e026b4b5a866d Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Tue, 17 Jun 2025 20:14:38 +0900 Subject: [PATCH 047/123] =?UTF-8?q?feat=20:=20Swagger=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20url=20=EC=9D=B8=EC=A6=9D=20X?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/filter/JwtFilter.java | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java index 28453ae..af3ebd5 100644 --- a/src/main/java/com/example/onederful/filter/JwtFilter.java +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -1,14 +1,17 @@ package com.example.onederful.filter; import com.example.onederful.security.JwtUtil; -import jakarta.servlet.*; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import java.io.IOException; - @Slf4j @RequiredArgsConstructor public class JwtFilter implements Filter { @@ -17,9 +20,9 @@ public class JwtFilter implements Filter { @Override public void doFilter( - ServletRequest servletRequest, - ServletResponse servletResponse, - FilterChain filterChain) throws IOException, ServletException { + ServletRequest servletRequest, + ServletResponse servletResponse, + FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; HttpServletResponse response = (HttpServletResponse) servletResponse; @@ -28,30 +31,34 @@ public void doFilter( String authorizationHeader = request.getHeader("Authorization"); - // 회원가입, 로그인 경우 - if(requestURI.startsWith("/api/auth/register") || requestURI.startsWith("/api/auth/login")){ + if (requestURI.startsWith("/api/auth/register") || requestURI.startsWith("/api/auth/login") + || + requestURI.startsWith("/swagger-ui") || + requestURI.startsWith("/v3/api-docs") || + requestURI.startsWith("/swagger-resources") || + requestURI.startsWith("/webjars")) { filterChain.doFilter(servletRequest, servletResponse); return; } // 토큰 존재 유무 확인 - if(authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")){ + if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { log.info("JWT 토큰이 필요합니다."); - response.sendError(response.SC_UNAUTHORIZED,"JWT 토큰이 필요합니다."); + response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "JWT 토큰이 필요합니다."); return; } // "Bearer" 빼고 확인 String jwt = authorizationHeader.substring(7); - + // 토큰 검증 유무 확인 - if(!jwtUtil.validateToken(jwt)){ + if (!jwtUtil.validateToken(jwt)) { response.setStatus(HttpServletResponse.SC_FORBIDDEN); response.getWriter().write("{\"error\": \"Unauthorized\"}"); return; } - filterChain.doFilter(servletRequest,servletResponse); + filterChain.doFilter(servletRequest, servletResponse); } } From 1ba91f24fe557b7c83ee9c1da0c2481e20a10d7d Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:17:12 +0900 Subject: [PATCH 048/123] =?UTF-8?q?feat=20:=20=EC=84=B1=EA=B3=B5,=20?= =?UTF-8?q?=EC=8B=A4=ED=8C=A8=20=EC=9D=91=EB=8B=B5=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=83=9D=EC=84=B1=20feat=20:=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/user/dto/ApiResponseDto.java | 11 +++++++++++ .../onederful/exception/GlobalExceptionHandler.java | 7 +------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java b/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java index 516bac9..7775c2a 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java @@ -13,4 +13,15 @@ public class ApiResponseDto { private String message; private Object data; private OffsetDateTime timestamp; + + // 성공 응답 static 메서드 + public static ApiResponseDto success(String message,Object date){ + return new ApiResponseDto(true, message , date, OffsetDateTime.now()); + } + + // 실패 응답 static 메서드 + public static ApiResponseDto error(String message){ + return new ApiResponseDto(false, message, null, OffsetDateTime.now()); + } + } diff --git a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java index 8b931af..3f766f1 100644 --- a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java @@ -14,12 +14,7 @@ public class GlobalExceptionHandler { public ResponseEntity handleCustomException(CustomException e){ ErrorCode errorCode = e.getErrorCode(); - ApiResponseDto response = new ApiResponseDto( - false, - errorCode.getMessage(), - null, - OffsetDateTime.now() - ); + ApiResponseDto response = ApiResponseDto.error(errorCode.getMessage()); return ResponseEntity.status(errorCode.getStatus()).body(response); } From b0794115e0f8e13c36ecad97724a5798e60cebe6 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:18:39 +0900 Subject: [PATCH 049/123] =?UTF-8?q?feat=20:=20groups=20=EC=B6=94=EA=B0=80?= =?UTF-8?q?=20=EC=82=AC=EC=9A=A9=20,=20=EC=9D=B8=ED=84=B0=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=8A=A4=20=EC=83=9D=EC=84=B1,=20=ED=9A=8C=EC=9B=90?= =?UTF-8?q?=20=ED=83=88=ED=87=B4=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/common/PasswordGroup.java | 4 ++ .../user/controller/AuthController.java | 31 +++++++-- .../onederful/domain/user/entity/User.java | 22 +++---- .../domain/user/service/UserService.java | 65 ++++++++++++++----- 4 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/user/common/PasswordGroup.java diff --git a/src/main/java/com/example/onederful/domain/user/common/PasswordGroup.java b/src/main/java/com/example/onederful/domain/user/common/PasswordGroup.java new file mode 100644 index 0000000..559625a --- /dev/null +++ b/src/main/java/com/example/onederful/domain/user/common/PasswordGroup.java @@ -0,0 +1,4 @@ +package com.example.onederful.domain.user.common; + +public interface PasswordGroup { +} diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java index 346040f..6792ea7 100644 --- a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -1,6 +1,7 @@ package com.example.onederful.domain.user.controller; import com.example.onederful.domain.user.common.LoginGroup; +import com.example.onederful.domain.user.common.PasswordGroup; import com.example.onederful.domain.user.common.SignupGroup; import com.example.onederful.domain.user.dto.*; import com.example.onederful.domain.user.service.UserService; @@ -22,27 +23,45 @@ public class AuthController { @PostMapping("/auth/register") public ResponseEntity register(@Validated(SignupGroup.class) @RequestBody RequestDto requestDto){ - ApiResponseDto signup = userService.signup(requestDto); + UserResponseDto signup = userService.signup(requestDto); - return ResponseEntity.status(HttpStatus.OK).body(signup); + ApiResponseDto success = ApiResponseDto.success("회원가입이 성공하였습니다.", signup); + + return ResponseEntity.status(HttpStatus.OK).body(success); } // 로그인 @PostMapping("/auth/login") public ResponseEntity login(@Validated(LoginGroup.class) @RequestBody RequestDto requestDto){ - ApiResponseDto login = userService.login(requestDto); + Tokeninfo token = userService.login(requestDto); + + ApiResponseDto success = ApiResponseDto.success("로그인이 완료되었습니다.", token); - return ResponseEntity.status(HttpStatus.OK).body(login); + return ResponseEntity.status(HttpStatus.OK).body(success); } // 현재 사용자 정보 조회 @GetMapping("/users/me") public ResponseEntity select (HttpServletRequest request){ - ApiResponseDto select = userService.select(request); + UserResponseDto select = userService.select(request); + + ApiResponseDto success = ApiResponseDto.success("사용자가 정보를 조회했습니다.", select); + + return ResponseEntity.status(HttpStatus.OK).body(success); + } + + // 회원 탈퇴 (계정 삭제) + @PostMapping("/auth/withdraw") + public ResponseEntity withdraw (HttpServletRequest request, + @Validated(PasswordGroup.class) @RequestBody RequestDto dto){ + + userService.withdraw(request,dto); + + ApiResponseDto success = ApiResponseDto.success("회원탈퇴가 완료되었습니다.", null); - return ResponseEntity.status(HttpStatus.OK).body(select); + return ResponseEntity.status(HttpStatus.OK).body(success); } diff --git a/src/main/java/com/example/onederful/domain/user/entity/User.java b/src/main/java/com/example/onederful/domain/user/entity/User.java index 647089c..f9674d7 100644 --- a/src/main/java/com/example/onederful/domain/user/entity/User.java +++ b/src/main/java/com/example/onederful/domain/user/entity/User.java @@ -1,21 +1,16 @@ package com.example.onederful.domain.user.entity; import com.example.onederful.domain.user.enums.Role; -import jakarta.persistence.Column; -import jakarta.persistence.Entity; -import jakarta.persistence.EntityListeners; -import jakarta.persistence.EnumType; -import jakarta.persistence.Enumerated; -import jakarta.persistence.GeneratedValue; -import jakarta.persistence.GenerationType; -import jakarta.persistence.Id; -import jakarta.persistence.Table; +import jakarta.persistence.*; + import java.time.LocalDateTime; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; +import org.hibernate.annotations.SQLDelete; +import org.hibernate.annotations.Where; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; import org.springframework.data.jpa.domain.support.AuditingEntityListener; @@ -27,6 +22,7 @@ @AllArgsConstructor @NoArgsConstructor(access = AccessLevel.PROTECTED) @EntityListeners(AuditingEntityListener.class) +@Where(clause = "is_deleted = false") public class User { @Id @@ -64,7 +60,11 @@ public class User { @Column(name="is_deleted", nullable = false) private Boolean isDeleted = false; - public void setEncodedPassword(String Password){ - this.password = Password; + public void setEncodedPassword(String encodedPassword){ + this.password = encodedPassword; + } + + public void delete() { + this.isDeleted = true; } } diff --git a/src/main/java/com/example/onederful/domain/user/service/UserService.java b/src/main/java/com/example/onederful/domain/user/service/UserService.java index e3dce19..d5b3eb4 100644 --- a/src/main/java/com/example/onederful/domain/user/service/UserService.java +++ b/src/main/java/com/example/onederful/domain/user/service/UserService.java @@ -11,6 +11,7 @@ import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; @Service @RequiredArgsConstructor @@ -20,8 +21,9 @@ public class UserService { private final UserRepository userRepository; private final JwtUtil jwtUtil; + @Transactional // 회원가입 - public ApiResponseDto signup(RequestDto dto){ + public UserResponseDto signup(RequestDto dto){ // 이메일 중복 확인 userRepository.findByEmail(dto.getEmail()).ifPresent( @@ -37,14 +39,12 @@ public ApiResponseDto signup(RequestDto dto){ User savedUser = userRepository.save(user); // ResponseBody data(유저 정보) - UserResponseDto data = UserMapper.data(savedUser); - - return UserMapper.signupResponse(data); + return UserMapper.data(savedUser); } // 로그인 - public ApiResponseDto login(RequestDto dto){ + public Tokeninfo login(RequestDto dto){ String username = dto.getUsername(); String password = dto.getPassword(); @@ -60,28 +60,59 @@ public ApiResponseDto login(RequestDto dto){ String token = jwtUtil.generateToken(user); // ResponseBody data(Token) - Tokeninfo data = UserMapper.token(token); - - return UserMapper.LoginResponse(data); + return token(token); } - + @Transactional // 회원 정보 조회 - public ApiResponseDto select(HttpServletRequest request){ - - // 요청 헤더에서 토큰 가져오기 - String authorizationHeader = request.getHeader("Authorization"); - String token = authorizationHeader.substring(7); + public UserResponseDto select(HttpServletRequest request){ + + // 토큰에서 Id 가져오기 + Long userId = tokenId(request); + + User user = userRepository.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + return UserMapper.data(user); + } + @Transactional + // 회원 탈퇴 + public void withdraw(HttpServletRequest request , RequestDto dto){ // 토큰에서 Id 가져오기 - Long userId = jwtUtil.extractId(token); + Long userId = tokenId(request); + + // 비밀번호 + String password = dto.getPassword(); User user = userRepository.findById(userId).orElseThrow( () -> new CustomException(ErrorCode.UNAUTHORIZED) ); - UserResponseDto data = UserMapper.data(user); + if (!passwordEncoder.matches(password,user.getPassword())) { + throw new CustomException(ErrorCode.INVALID_PASSWORD); + } + + user.delete(); + } + + + // ResponseBody date (Token) + private Tokeninfo token (String token){ + + String newToken = token.substring(7); - return UserMapper.selectResponse(data); + return new Tokeninfo(newToken); + } + + // 토큰 Id 가져오기 + private Long tokenId (HttpServletRequest request){ + // 요청 헤더에서 토큰 가져오기 + String authorizationHeader = request.getHeader("Authorization"); + String token = authorizationHeader.substring(7); + + // 토큰에서 Id 가져오기 + return jwtUtil.extractId(token); } } From c3725f72b2526a0e2080ab0cc990a84f7f62fcfc Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:19:31 +0900 Subject: [PATCH 050/123] =?UTF-8?q?refactor=20:=20=EA=B0=80=EB=8F=85?= =?UTF-8?q?=EC=84=B1=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/common/UserMapper.java | 52 ++----------------- .../onederful/domain/user/dto/RequestDto.java | 6 +-- 2 files changed, 6 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/common/UserMapper.java b/src/main/java/com/example/onederful/domain/user/common/UserMapper.java index 21017f3..b12f9f2 100644 --- a/src/main/java/com/example/onederful/domain/user/common/UserMapper.java +++ b/src/main/java/com/example/onederful/domain/user/common/UserMapper.java @@ -1,16 +1,15 @@ package com.example.onederful.domain.user.common; - import com.example.onederful.domain.user.dto.*; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.enums.Role; - import java.time.OffsetDateTime; import java.time.ZoneOffset; -import java.util.Date; + public class UserMapper { + // Dto → Entity public static User user (RequestDto dto){ return User.builder() .username(dto.getUsername()) @@ -22,7 +21,7 @@ public static User user (RequestDto dto){ .build(); } - // ResponseBody data (유저 정보) + // ResponseBody data (유저 정보) (Entity → Dto) public static UserResponseDto data(User user){ // LocalDateTime -> OffsetDateTime OffsetDateTime createAt = user.getCreatedAt().atOffset(ZoneOffset.UTC); @@ -37,50 +36,5 @@ public static UserResponseDto data(User user){ ); } - // ResponseBody date (Token) - public static Tokeninfo token (String token){ - - String newToken = token.substring(7); - - return new Tokeninfo(newToken); - } - - // ResponseBody createdAt - public static OffsetDateTime currentTime(){ - Date date = new Date(); - return date.toInstant().atOffset(ZoneOffset.UTC); - } - - // 회원가입 ResponseBody - public static ApiResponseDto signupResponse(UserResponseDto data){ - - return new ApiResponseDto( - true, - "회원가입이 성공하였습니다", - data, - currentTime() - ); - } - - // 로그인 ResponseBody - public static ApiResponseDto LoginResponse (Tokeninfo data){ - - return new ApiResponseDto( - true, - "로그인이 완료되었습니다.", - data, - currentTime() - ); - } - - // 회원 정보 조회 - public static ApiResponseDto selectResponse(UserResponseDto data){ - return new ApiResponseDto( - true, - "사용자가 정보를 조회했습니다.", - data, - currentTime() - ); - } } diff --git a/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java index 457dbcb..8f29906 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java @@ -1,6 +1,7 @@ package com.example.onederful.domain.user.dto; import com.example.onederful.domain.user.common.LoginGroup; +import com.example.onederful.domain.user.common.PasswordGroup; import com.example.onederful.domain.user.common.SignupGroup; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; @@ -21,8 +22,8 @@ public class RequestDto { @Email (groups = {SignupGroup.class}, message = "올바른 형식의 이메일 주소를 입력해주세요") private String email; - @NotBlank (groups = {SignupGroup.class,LoginGroup.class}) - @Pattern (groups = {SignupGroup.class,LoginGroup.class}, + @NotBlank (groups = {SignupGroup.class,LoginGroup.class, PasswordGroup.class}) + @Pattern (groups = {SignupGroup.class,LoginGroup.class, PasswordGroup.class}, regexp = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^\\w\\s]).+$", message = "비밀번호는 대문자·소문자·숫자·특수문자를 각각 1자 이상 포함해야 합니다." ) @@ -30,5 +31,4 @@ public class RequestDto { @NotBlank (groups = {SignupGroup.class}) private String name; - } From f14fd05b5963a6b859fafc3cf3413e4af820fb6d Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:21:16 +0900 Subject: [PATCH 051/123] =?UTF-8?q?refactor=20:=20ApiResponseDto=20?= =?UTF-8?q?=EC=9C=84=EC=B9=98=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/{user/dto => comment}/ApiResponseDto.java | 2 +- .../onederful/domain/user/controller/AuthController.java | 1 + .../example/onederful/exception/GlobalExceptionHandler.java | 4 +--- 3 files changed, 3 insertions(+), 4 deletions(-) rename src/main/java/com/example/onederful/domain/{user/dto => comment}/ApiResponseDto.java (93%) diff --git a/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java b/src/main/java/com/example/onederful/domain/comment/ApiResponseDto.java similarity index 93% rename from src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java rename to src/main/java/com/example/onederful/domain/comment/ApiResponseDto.java index 7775c2a..ba4c1bb 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/ApiResponseDto.java +++ b/src/main/java/com/example/onederful/domain/comment/ApiResponseDto.java @@ -1,4 +1,4 @@ -package com.example.onederful.domain.user.dto; +package com.example.onederful.domain.comment; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java index 6792ea7..9244daf 100644 --- a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -1,5 +1,6 @@ package com.example.onederful.domain.user.controller; +import com.example.onederful.domain.comment.ApiResponseDto; import com.example.onederful.domain.user.common.LoginGroup; import com.example.onederful.domain.user.common.PasswordGroup; import com.example.onederful.domain.user.common.SignupGroup; diff --git a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java index 3f766f1..4b550b2 100644 --- a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java @@ -1,12 +1,10 @@ package com.example.onederful.exception; -import com.example.onederful.domain.user.dto.ApiResponseDto; +import com.example.onederful.domain.comment.ApiResponseDto; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; -import java.time.OffsetDateTime; - @ControllerAdvice public class GlobalExceptionHandler { From 149b3f4bc32a0c5d5caf8fa25e7f7c10e1a0dbd5 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:21:57 +0900 Subject: [PATCH 052/123] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20import=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/onederful/domain/user/entity/User.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/example/onederful/domain/user/entity/User.java b/src/main/java/com/example/onederful/domain/user/entity/User.java index f9674d7..83554be 100644 --- a/src/main/java/com/example/onederful/domain/user/entity/User.java +++ b/src/main/java/com/example/onederful/domain/user/entity/User.java @@ -9,7 +9,6 @@ import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.annotations.SQLDelete; import org.hibernate.annotations.Where; import org.springframework.data.annotation.CreatedDate; import org.springframework.data.annotation.LastModifiedDate; From 5ee9cd78db171908f7c845614c1c19734d17946e Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:45:05 +0900 Subject: [PATCH 053/123] =?UTF-8?q?refactor=20:=20=EC=9C=84=EC=B9=98=20?= =?UTF-8?q?=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/{domain/comment => common}/ApiResponseDto.java | 2 +- .../onederful/domain/user/controller/AuthController.java | 2 +- .../com/example/onederful/exception/GlobalExceptionHandler.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) rename src/main/java/com/example/onederful/{domain/comment => common}/ApiResponseDto.java (93%) diff --git a/src/main/java/com/example/onederful/domain/comment/ApiResponseDto.java b/src/main/java/com/example/onederful/common/ApiResponseDto.java similarity index 93% rename from src/main/java/com/example/onederful/domain/comment/ApiResponseDto.java rename to src/main/java/com/example/onederful/common/ApiResponseDto.java index ba4c1bb..9189271 100644 --- a/src/main/java/com/example/onederful/domain/comment/ApiResponseDto.java +++ b/src/main/java/com/example/onederful/common/ApiResponseDto.java @@ -1,4 +1,4 @@ -package com.example.onederful.domain.comment; +package com.example.onederful.common; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java index 9244daf..844f203 100644 --- a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -1,6 +1,6 @@ package com.example.onederful.domain.user.controller; -import com.example.onederful.domain.comment.ApiResponseDto; +import com.example.onederful.common.ApiResponseDto; import com.example.onederful.domain.user.common.LoginGroup; import com.example.onederful.domain.user.common.PasswordGroup; import com.example.onederful.domain.user.common.SignupGroup; diff --git a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java index 4b550b2..cfe7bb5 100644 --- a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java @@ -1,6 +1,6 @@ package com.example.onederful.exception; -import com.example.onederful.domain.comment.ApiResponseDto; +import com.example.onederful.common.ApiResponseDto; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; From d3e4c7f6756e1bf9321d856899761a18ed6ed124 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 20:54:38 +0900 Subject: [PATCH 054/123] =?UTF-8?q?refactor:=20userId=20=EB=B0=9B=EC=95=84?= =?UTF-8?q?=EC=98=A4=EB=8A=94=20=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 - .../comment/controller/CommentController.java | 14 +++++--------- .../onederful/domain/comment/entity/Comment.java | 2 ++ .../domain/comment/service/CommentService.java | 15 +++++++++++++-- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 4d3cc50..22f4c2e 100644 --- a/build.gradle +++ b/build.gradle @@ -27,7 +27,6 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-validation' implementation 'org.springframework.boot:spring-boot-starter-web' - //implementation 'org.springframework.boot:spring-boot-starter-security' compileOnly 'org.projectlombok:lombok' runtimeOnly 'com.mysql:mysql-connector-j' annotationProcessor 'org.projectlombok:lombok' diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 9b39043..89f6e4c 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -2,12 +2,10 @@ import com.example.onederful.domain.comment.dto.*; import com.example.onederful.domain.comment.service.CommentService; -import com.example.onederful.domain.user.entity.User; -import com.example.onederful.domain.user.repository.UserRepository; +import jakarta.servlet.http.HttpServletRequest; 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 java.util.List; @@ -18,15 +16,13 @@ public class CommentController { private final CommentService commentService; - private final UserRepository userRepository; // 댓글 생성 @PostMapping("/comments") - - public ResponseEntity> save (@AuthenticationPrincipal Long userId, @RequestBody CreateCommentRequestDto requestDto){ + public ResponseEntity> save (HttpServletRequest httpServletRequest, @RequestBody CreateCommentRequestDto requestDto){ CreateCommentResponseDataDto createCommentResponseDataDto = - commentService.save(userId, requestDto.getContents()); + commentService.save(httpServletRequest, requestDto.getContents()); ResponseDto responseDto = ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto); return ResponseEntity.ok(responseDto); @@ -35,10 +31,10 @@ public ResponseEntity> save (@Authenti // 댓글 수정 @PatchMapping("/comments/{comment_id}") public ResponseEntity> updateComment( - @PathVariable Long commentId, @RequestBody UpdateCommentRequestDto requestDto, @AuthenticationPrincipal Long userId + @PathVariable Long commentId, @RequestBody UpdateCommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { UpdateCommentResponseDataDto updateCommentResponseDataDto = - commentService.updateComment(commentId, requestDto.getContents(), userId); + commentService.updateComment(commentId, requestDto.getContents(), httpServletRequest); return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); } diff --git a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java index 411d849..13fb5e2 100644 --- a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java +++ b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java @@ -68,11 +68,13 @@ public Comment(String contents, User user){ this.user = user; this.contents = contents; this.createdAt = LocalDateTime.now(); + this.isDeleted = false; } public void update(String contents){ this.contents = contents; this.updatedAt = LocalDateTime.now(); + this.isDeleted = false; } public void delete(){ diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index a226f28..7a20b84 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -6,8 +6,12 @@ import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.repository.TaskRepository; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.security.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -21,8 +25,12 @@ public class CommentService { private final CommentRepository commentRepository; private final UserRepository userRepository; + private final JwtUtil jwtUtil; - public CreateCommentResponseDataDto save(Long userId, String contents) { + public CreateCommentResponseDataDto save(HttpServletRequest httpServletRequest, String contents) { + + // 토큰에서 Id 가져오기 + Long userId = jwtUtil.extractId(httpServletRequest); User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); @@ -35,10 +43,13 @@ public CreateCommentResponseDataDto save(Long userId, String contents) { } @Transactional - public UpdateCommentResponseDataDto updateComment(Long commentId, String contents, Long userId) { + public UpdateCommentResponseDataDto updateComment(Long commentId, String contents, HttpServletRequest httpServletRequest) { Comment comment = commentRepository.findById(commentId) .orElseThrow(() ->new IllegalArgumentException("댓글을 찾을 수 없습니다.")); + // 토큰에서 Id 가져오기 + Long userId = jwtUtil.extractId(httpServletRequest); + User user = userRepository.findById(userId) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); From e308774958cb636c343a61df4421a85757677f3a Mon Sep 17 00:00:00 2001 From: DongGeun Date: Tue, 17 Jun 2025 20:58:07 +0900 Subject: [PATCH 055/123] =?UTF-8?q?feat=20:=20jwt=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A4=91=20(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/filter/JwtFilter.java | 43 ++++++++++++++++--- .../example/onederful/security/JwtUtil.java | 14 +----- 2 files changed, 37 insertions(+), 20 deletions(-) diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java index 28453ae..ec912c4 100644 --- a/src/main/java/com/example/onederful/filter/JwtFilter.java +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -1,6 +1,11 @@ package com.example.onederful.filter; import com.example.onederful.security.JwtUtil; +import io.jsonwebtoken.ExpiredJwtException; +import io.jsonwebtoken.MalformedJwtException; +import io.jsonwebtoken.UnsupportedJwtException; +import io.jsonwebtoken.security.SecurityException; +import io.jsonwebtoken.security.SignatureException; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @@ -8,6 +13,7 @@ import lombok.extern.slf4j.Slf4j; import java.io.IOException; +import java.time.OffsetDateTime; @Slf4j @RequiredArgsConstructor @@ -37,21 +43,44 @@ public void doFilter( // 토큰 존재 유무 확인 if(authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")){ - log.info("JWT 토큰이 필요합니다."); - response.sendError(response.SC_UNAUTHORIZED,"JWT 토큰이 필요합니다."); + errorResponse(response,HttpServletResponse.SC_UNAUTHORIZED,"인증이 필요합니다"); return; } // "Bearer" 빼고 확인 String jwt = authorizationHeader.substring(7); - // 토큰 검증 유무 확인 - if(!jwtUtil.validateToken(jwt)){ - response.setStatus(HttpServletResponse.SC_FORBIDDEN); - response.getWriter().write("{\"error\": \"Unauthorized\"}"); - return; + // 토큰 검증 유무 확인 (응답 형태가 올바르지 못한 상태) + try { + jwtUtil.validateToken(jwt); + } + catch (SignatureException e) { + errorResponse(response, HttpServletResponse.SC_FORBIDDEN, "유효하지 않은 JWT 서명입니다."); + } catch (SecurityException | MalformedJwtException e){ + errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"잘못된 JWT 토큰 형식입니다."); + }catch (ExpiredJwtException e){ + errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"Expired JWT token, 만료된 JWT token 입니다."); + }catch (UnsupportedJwtException e){ + errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"Unsupported JWT token, 지원되지 않는 JWT 토큰 입니다."); + }catch (IllegalArgumentException e){ + errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"JWT claims is empty, 잘못된 JWT 토큰 입니다."); } + filterChain.doFilter(servletRequest,servletResponse); } + + private void errorResponse(HttpServletResponse response, int status, String message) throws IOException { + response.setStatus(status); + response.setContentType("application/json;charset=utf-8"); + + String json = "{" + + "\"success\" : false," + + "\"message\": \""+ message + "\"," + + "\"data\" : null," + + "\"timestamp\" : \"" + OffsetDateTime.now() + "\"" + + "}"; + + response.getWriter().write(json); + } } diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java index 6b73706..d062b41 100644 --- a/src/main/java/com/example/onederful/security/JwtUtil.java +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -73,23 +73,11 @@ public String generateToken(User user){ * @param token JWT 토큰 * @return 토큰의 유효성 여부 (true : 유효, false : 유효하지 않음) */ - public boolean validateToken(String token){ - try { + public void validateToken(String token){ Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); - return true; - }catch (SecurityException | MalformedJwtException e){ - log.error("Invalid JWT signature, 유효하지 않은 JWT 서명입니다."); - }catch (ExpiredJwtException e){ - log.error("Expired JWT token, 만료된 JWT token 입니다.", e); - }catch (UnsupportedJwtException e){ - log.error("Unsupported JWT token, 지원되지 않는 JWT 토큰 입니다.", e); - }catch (IllegalArgumentException e){ - log.error("JWT claims is empty, 잘못된 JWT 토큰 입니다.", e); - } - return false; } /** From 72b4f9843493909b29f952372e0a5552055983f9 Mon Sep 17 00:00:00 2001 From: saevit Date: Tue, 17 Jun 2025 21:13:53 +0900 Subject: [PATCH 056/123] =?UTF-8?q?feat:=20task=20=EC=83=9D=EC=84=B1,=20?= =?UTF-8?q?=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B8=B0=EB=A1=9D=EB=90=98=EB=A1=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/HttpRequestUtil.java | 6 ++-- .../onederful/domain/log/LoggingAspect.java | 16 ++++----- .../domain/log/controller/LogController.java | 29 +++++++--------- .../domain/log/dto/addLogTestDto.java | 10 ------ .../onederful/domain/log/enums/Activity.java | 11 +++--- .../domain/log/service/LogService.java | 34 ++++++++----------- 6 files changed, 42 insertions(+), 64 deletions(-) delete mode 100644 src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java diff --git a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java index 567fbc2..e662029 100644 --- a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java +++ b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java @@ -39,10 +39,8 @@ public RequestInfo getRequestInfo() { // 요청 url String url = request.getRequestURI(); - // 요청 헤더의 토큰으로부터 요청한 사용자의 userId - String authorizationHeader = request.getHeader("Authorization"); - String token = authorizationHeader.substring(7); - Long userId = jwtUtil.extractId(token); + // 토큰으로부터 요청한 사용자의 userId + Long userId = jwtUtil.extractId(request); return new RequestInfo(ip, enumMethod, url, userId); } diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index 894dcaa..7a14953 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -5,13 +5,9 @@ import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; -import org.springframework.web.context.request.RequestContextHolder; -import org.springframework.web.context.request.ServletRequestAttributes; -import com.example.onederful.domain.log.enums.Method; import com.example.onederful.domain.log.service.LogService; -import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @Aspect @@ -22,15 +18,19 @@ public class LoggingAspect { private final HttpRequestUtil httpRequestUtil; private final LogService logService; - @Pointcut("execution(* com.example..LogService.addLogTest1()) || execution(* com.example..LogService.addLogTest2())") - public void serviceMethods() {} + @Pointcut( + "execution(* com.example..TaskService.createTask(..)) || " + + "execution(* com.example..TaskService.updateTask(..)) || " + + "execution(* com.example..TaskService.deleteTask(..))" + ) + public void cudMethods() {} @Pointcut("execution(* com.example..userService.login())") public void loginMethods() {} // 생성, 수정, 삭제 - @AfterReturning(pointcut = "serviceMethods()", returning = "result") - public void logAfterReturning(JoinPoint joinPoint, Object result) { + @AfterReturning(pointcut = "cudMethods()", returning = "result") + public void logCudMethods(JoinPoint joinPoint, Object result) { System.out.println("메서드 정상 실행 후: 로그 기록"); // HttpServletRequest으로부터 요청 ip, 메서드, url diff --git a/src/main/java/com/example/onederful/domain/log/controller/LogController.java b/src/main/java/com/example/onederful/domain/log/controller/LogController.java index f47ae09..3686074 100644 --- a/src/main/java/com/example/onederful/domain/log/controller/LogController.java +++ b/src/main/java/com/example/onederful/domain/log/controller/LogController.java @@ -5,22 +5,15 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; -import org.springframework.data.repository.query.Param; import org.springframework.data.web.PageableDefault; import org.springframework.format.annotation.DateTimeFormat; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.PathVariable; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import com.example.onederful.domain.log.dto.LogResponseDto; -import com.example.onederful.domain.log.dto.addLogTestDto; -import com.example.onederful.domain.log.enums.Activity; import com.example.onederful.domain.log.service.LogService; import lombok.RequiredArgsConstructor; @@ -31,16 +24,18 @@ public class LogController { private final LogService logService; - @PostMapping("/api/activities") - public ResponseEntity addLogTest1() { - return new ResponseEntity<>(logService.addLogTest1(), HttpStatus.OK); - } - - @DeleteMapping("/api/activities/{id}") - public void addLogTest2(@PathVariable Long id) { - logService.addLogTest2(); - } - + /** + * 활동 로그 조회 + * + * 검색 조건: + * @param userId 유저 아이디 (필수 N) + * @param activity 활동 유형 (필수 N) + * @param targetId 대상 ID (필수 N) + * @param start 시작일 (필수 N) + * @param end 종료일 (필수 N) + * @param pageable 페이징을 위한 page, size, sort (필수 N) + * @return 조회된 활동 로그 + */ @GetMapping("/api/activities") public ResponseEntity> getLog( @RequestParam(required = false) Long userId, diff --git a/src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java b/src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java deleted file mode 100644 index 8ab6a02..0000000 --- a/src/main/java/com/example/onederful/domain/log/dto/addLogTestDto.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.example.onederful.domain.log.dto; - -import lombok.Getter; - -@Getter -public class addLogTestDto { - Long id; - - public addLogTestDto(Long id) {this.id = id;}; -} diff --git a/src/main/java/com/example/onederful/domain/log/enums/Activity.java b/src/main/java/com/example/onederful/domain/log/enums/Activity.java index 7bf57d2..929cb54 100644 --- a/src/main/java/com/example/onederful/domain/log/enums/Activity.java +++ b/src/main/java/com/example/onederful/domain/log/enums/Activity.java @@ -1,18 +1,17 @@ package com.example.onederful.domain.log.enums; public enum Activity { - // TASK_CREATED, - // TASK_UPDATED, - // TASK_DELETED, + TASK_CREATED("새로운 작업이 생성되었습니다."), + TASK_UPDATED("작업이 수정되었습니다."), + TASK_DELETED("작업이 삭제되었습니다."); // TASK_STATUS_TODO_TO_IN_PROGRESS, // TASK_STATUS_IN_PROGRESS_TO_DONE, // TASK_STATUS_TODO_TO_DONE, // COMMENT_CREATED, // COMMENT_UPDATED, // COMMENT_DELETED, - USER_LOGGED_IN("로그인 하였습니다."), - USER_LOGGED_OUT("로그아웃 하였습니다."), - TEST("테스트 입니다."); + // USER_LOGGED_IN("로그인 하였습니다."), + // USER_LOGGED_OUT("로그아웃 하였습니다.") private final String logMessage; diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index 687d12f..f7043e3 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -8,14 +8,13 @@ import org.springframework.stereotype.Service; import com.example.onederful.domain.log.dto.LogResponseDto; -import com.example.onederful.domain.log.dto.addLogTestDto; import com.example.onederful.domain.log.entity.Log; import com.example.onederful.domain.log.enums.Activity; import com.example.onederful.domain.log.enums.Method; import com.example.onederful.domain.log.repository.LogRepository; import com.example.onederful.domain.log.repository.LogSpecification; +import com.example.onederful.domain.task.dto.response.TaskResponse; import com.example.onederful.domain.user.entity.User; -import com.example.onederful.domain.user.enums.Role; import com.example.onederful.domain.user.repository.UserRepository; import com.example.onederful.exception.CustomException; import com.example.onederful.exception.ErrorCode; @@ -30,13 +29,6 @@ public class LogService { private final LogRepository logRepository; private final UserRepository userRepositry; - public addLogTestDto addLogTest1() { - return new addLogTestDto(1L); - } - - public void addLogTest2() { - } - public Page getLog( Long userId, String activityStr, Long targetId, LocalDate start, LocalDate end, Pageable pageable) { @@ -60,30 +52,34 @@ public void saveLog(String ip, Method method, String url, Long userId, Object re () -> new CustomException(ErrorCode.UNAUTHORIZED) ); - // TODO: 어떤 활동인지, 대상 id 찾기 // 활동 유형 -> 요청 메서드와 url로 일치하는 활동 유형 찾기 Activity activity = null; - if (method.equals(Method.POST) && url.contains("/activities")) { - activity = Activity.TEST; + if (method.equals(Method.POST) && url.contains("/tasks")) { + activity = Activity.TASK_CREATED; + } + else if (method.equals(Method.PUT) && url.contains("/tasks")) { + activity = Activity.TASK_UPDATED; } - else if (method.equals(Method.DELETE) && url.contains("/activities")) { - activity = Activity.TEST; + else if (method.equals(Method.DELETE) && url.contains("/tasks")) { + activity = Activity.TASK_DELETED; } + // if (activity == null) 예외 처리 + // 대상 id -> 생성인 경우 응답에서 / 수정과 삭제의 경우 url 마지막에서 찾기 Long targetId = null; - if (method.equals(Method.POST)) { - if (result instanceof addLogTestDto) { - targetId = ((addLogTestDto) result).getId(); + if (activity.equals(Activity.TASK_CREATED)) { + if (result instanceof TaskResponse) { + targetId = ((TaskResponse) result).getId(); } } - else if (method.equals(Method.PATCH) || method.equals(Method.DELETE)) { + else { String[] parts = url.split("/"); String lastPart = parts[parts.length - 1]; // /api/.../{id}의 id targetId = Long.parseLong(lastPart); } - // if (activity == null || targetId == null) 예외 처리 + // if (targetId == null) 예외 처리 Log log = Log.builder() .user(user) From 2cd20532c6bbcf14b290b1b8d2c925d66c9b1703 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Tue, 17 Jun 2025 22:44:35 +0900 Subject: [PATCH 057/123] =?UTF-8?q?refactor:=20api=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B3=80=EC=88=98=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 32 +++++++++---------- .../comment/dto/CommentResponseDataDto.java | 8 ++--- .../comment/dto/CreateCommentRequestDto.java | 6 ++-- .../dto/CreateCommentResponseDataDto.java | 6 ++-- .../dto/FindCommentByContentRequestDto.java | 14 ++++++++ .../comment/dto/UpdateCommentRequestDto.java | 6 ++-- .../dto/UpdateCommentResponseDataDto.java | 6 ++-- .../domain/comment/entity/Comment.java | 13 ++++---- .../comment/repository/CommentRepository.java | 2 +- .../comment/service/CommentService.java | 28 +++++++++------- 10 files changed, 70 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 89f6e4c..9471b13 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -18,46 +18,46 @@ public class CommentController { private final CommentService commentService; // 댓글 생성 - @PostMapping("/comments") - public ResponseEntity> save (HttpServletRequest httpServletRequest, @RequestBody CreateCommentRequestDto requestDto){ + @PostMapping("/tasks/{task_id}/comments") + public ResponseEntity> save (@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CreateCommentRequestDto requestDto){ CreateCommentResponseDataDto createCommentResponseDataDto = - commentService.save(httpServletRequest, requestDto.getContents()); + commentService.save(task_id,httpServletRequest, requestDto.getContent()); ResponseDto responseDto = ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto); return ResponseEntity.ok(responseDto); } // 댓글 수정 - @PatchMapping("/comments/{comment_id}") + @PatchMapping("/tasks/{task_id}/comments/{comment_id}") public ResponseEntity> updateComment( - @PathVariable Long commentId, @RequestBody UpdateCommentRequestDto requestDto, HttpServletRequest httpServletRequest + @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody UpdateCommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { UpdateCommentResponseDataDto updateCommentResponseDataDto = - commentService.updateComment(commentId, requestDto.getContents(), httpServletRequest); + commentService.updateComment(comment_id, requestDto.getContent(), httpServletRequest); return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); } // 테스크별 댓글 조회 - @GetMapping("/comments/task/{task_id}") + @GetMapping("/tasks/{task_id}/comments") public ResponseEntity>> findAllCommentByTaskId( - @PathVariable Long taskId) { - List commentResponseDataDtoList = commentService.findAllCommentByTaskId(taskId); - return ResponseEntity.ok(ResponseDto.success("task " + taskId + "에 달린 댓글 목록", commentResponseDataDtoList)); + @PathVariable Long task_id) { + List commentResponseDataDtoList = commentService.findAllCommentByTaskId(task_id); + return ResponseEntity.ok(ResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDataDtoList)); } // 내용으로 댓글 조회 @GetMapping("/search") - public ResponseEntity>> findCommentByContents(@RequestBody String contents){ - List commentResponseDataDtoList = commentService.findCommentByContents(contents); - return ResponseEntity.ok(ResponseDto.success( contents + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); + public ResponseEntity>> findCommentByContent(@RequestBody FindCommentByContentRequestDto requestDto){ + List commentResponseDataDtoList = commentService.findCommentByContent(requestDto.getContent()); + return ResponseEntity.ok(ResponseDto.success( requestDto.getContent() + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); } // 댓글 삭제 - @DeleteMapping("/comments/{comment_id}") - public ResponseEntity> deleteComment(@PathVariable Long commentId){ - commentService.deleteComment(commentId); + @DeleteMapping("/tasks/{task_id}/comments/{comment_id}") + public ResponseEntity> deleteComment(@PathVariable Long task_id, @PathVariable Long comment_id){ + commentService.deleteComment(comment_id); return ResponseEntity.ok(ResponseDto.success("댓글이 삭제되었습니다.", null)); } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java index ff1d62c..90905a4 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java @@ -9,14 +9,14 @@ @Getter public class CommentResponseDataDto { private final String writer; - private final String contents; + private final String content; private final LocalDateTime createdAt; private final LocalDateTime updatedAt; - public CommentResponseDataDto(String writer, String contents, LocalDateTime createdAt, LocalDateTime updatedAt) { + public CommentResponseDataDto(String writer, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { this.writer = writer; - this.contents = contents; + this.content = content; this.createdAt = createdAt; this.updatedAt = updatedAt; } @@ -24,7 +24,7 @@ public CommentResponseDataDto(String writer, String contents, LocalDateTime crea public static CommentResponseDataDto from(Comment comment){ return new CommentResponseDataDto( comment.getUser().getName(), - comment.getContents(), + comment.getContent(), comment.getCreatedAt(), comment.getUpdatedAt() ); diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java index 33258bb..1095315 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java @@ -5,10 +5,10 @@ @Getter public class CreateCommentRequestDto { - private final String contents; + private final String content; - public CreateCommentRequestDto(String writer, String contents) { - this.contents = contents; + public CreateCommentRequestDto(String writer, String content) { + this.content = content; } } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java index 4a19895..e04c8e3 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java @@ -7,12 +7,12 @@ public class CreateCommentResponseDataDto { private final Long id; private final String writer; - private final String contents; + private final String content; - public CreateCommentResponseDataDto(Long id, String writer, String contents){ + public CreateCommentResponseDataDto(Long id, String writer, String content){ this.id = id; this.writer = writer; - this.contents = contents; + this.content = content; } } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java new file mode 100644 index 0000000..59833b3 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java @@ -0,0 +1,14 @@ +package com.example.onederful.domain.comment.dto; + +import lombok.Getter; + +@Getter +public class FindCommentByContentRequestDto { + + private final String content; + + + public FindCommentByContentRequestDto(String content) { + this.content = content; + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java index ff9ca54..c3950ea 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java @@ -5,9 +5,9 @@ @Getter public class UpdateCommentRequestDto { - private final String contents; + private final String content; - public UpdateCommentRequestDto(String contents){ - this.contents = contents; + public UpdateCommentRequestDto(String content){ + this.content = content; } } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java index 8fa80d8..9e49201 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java @@ -10,15 +10,15 @@ public class UpdateCommentResponseDataDto { private final Long id; private final String writer; - private final String contents; + private final String content; private final LocalDateTime created_at; private final LocalDateTime updated_at; - public UpdateCommentResponseDataDto(Long id, String writer, String contents, LocalDateTime createdAt, LocalDateTime updatedAt) { + public UpdateCommentResponseDataDto(Long id, String writer, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { this.id = id; this.writer = writer; - this.contents = contents; + this.content = content; this.created_at = createdAt; this.updated_at = updatedAt; } diff --git a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java index 13fb5e2..4ff00a4 100644 --- a/src/main/java/com/example/onederful/domain/comment/entity/Comment.java +++ b/src/main/java/com/example/onederful/domain/comment/entity/Comment.java @@ -38,8 +38,8 @@ public class Comment { @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - @Column(name = "contents", nullable = false) - private String contents; + @Column(name = "content", nullable = false) + private String content; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name= "task_id", nullable = false) @@ -64,15 +64,16 @@ public class Comment { @Column(name="is_deleted", nullable = false) private Boolean isDeleted = false; - public Comment(String contents, User user){ + public Comment(String content, User user, Task task){ this.user = user; - this.contents = contents; + this.content = content; + this.task = task; this.createdAt = LocalDateTime.now(); this.isDeleted = false; } - public void update(String contents){ - this.contents = contents; + public void update(String content){ + this.content = content; this.updatedAt = LocalDateTime.now(); this.isDeleted = false; } diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java index d51bdb4..068b3b9 100644 --- a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -9,5 +9,5 @@ public interface CommentRepository extends JpaRepository { List findAllByTaskIdOrderByCreatedAtDesc(Long taskId); - List findByContentsLike(String contents); + List findBycontentLike(String content); } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 7a20b84..8dd2473 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -25,26 +25,30 @@ public class CommentService { private final CommentRepository commentRepository; private final UserRepository userRepository; + private final TaskRepository taskRepository; private final JwtUtil jwtUtil; - public CreateCommentResponseDataDto save(HttpServletRequest httpServletRequest, String contents) { + public CreateCommentResponseDataDto save(Long task_id, HttpServletRequest httpServletRequest, String content) { // 토큰에서 Id 가져오기 - Long userId = jwtUtil.extractId(httpServletRequest); + Long user_id = jwtUtil.extractId(httpServletRequest); - User user = userRepository.findById(userId) + User user = userRepository.findById(user_id) .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); - Comment comment = new Comment(contents, user); + Task task = taskRepository.findById(task_id) + .orElseThrow(() -> new IllegalArgumentException("테스크를 찾을 수 없습니다.")); + + Comment comment = new Comment(content, user, task); Comment savedComment = commentRepository.save(comment); - return new CreateCommentResponseDataDto(savedComment.getId(), user.getName(), savedComment.getContents()); + return new CreateCommentResponseDataDto(savedComment.getId(), user.getName(), savedComment.getContent()); } @Transactional - public UpdateCommentResponseDataDto updateComment(Long commentId, String contents, HttpServletRequest httpServletRequest) { - Comment comment = commentRepository.findById(commentId) + public UpdateCommentResponseDataDto updateComment(Long comment_id, String content, HttpServletRequest httpServletRequest) { + Comment comment = commentRepository.findById(comment_id) .orElseThrow(() ->new IllegalArgumentException("댓글을 찾을 수 없습니다.")); // 토큰에서 Id 가져오기 @@ -57,8 +61,8 @@ public UpdateCommentResponseDataDto updateComment(Long commentId, String content throw new IllegalArgumentException("삭제된 댓글입니다."); } - comment.update(contents); - return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContents(),comment.getCreatedAt(), comment.getUpdatedAt()); + comment.update(content); + return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContent(),comment.getCreatedAt(), comment.getUpdatedAt()); } public List findAllCommentByTaskId(Long taskId){ @@ -71,11 +75,11 @@ public List findAllCommentByTaskId(Long taskId){ } - public List findCommentByContents(String contents){ + public List findCommentByContent(String content){ - List commentListByContents = commentRepository.findByContentsLike("%"+contents+"%"); + List commentListByContent = commentRepository.findBycontentLike("%"+content+"%"); - return commentListByContents.stream() + return commentListByContent.stream() .filter(comment -> !comment.getIsDeleted()) .map(CommentResponseDataDto::from) .collect(Collectors.toList()); From 200d3f29d1f4f9aa27179b57a2378217ac664718 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 09:35:16 +0900 Subject: [PATCH 058/123] =?UTF-8?q?feat=20:=20jwt=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A4=91=20(=EB=AF=B8=EC=99=84=EC=84=B1)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/onederful/filter/JwtFilter.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java index ec912c4..8f97ba7 100644 --- a/src/main/java/com/example/onederful/filter/JwtFilter.java +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -1,6 +1,7 @@ package com.example.onederful.filter; import com.example.onederful.security.JwtUtil; +import com.fasterxml.jackson.databind.ObjectMapper; import io.jsonwebtoken.ExpiredJwtException; import io.jsonwebtoken.MalformedJwtException; import io.jsonwebtoken.UnsupportedJwtException; @@ -11,6 +12,8 @@ import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; import java.io.IOException; import java.time.OffsetDateTime; @@ -83,4 +86,12 @@ private void errorResponse(HttpServletResponse response, int status, String mess response.getWriter().write(json); } + +// private void errorResponse(HttpServletResponse response, String message) throws IOException{ +// ObjectMapper objectMapper = new ObjectMapper(); +// response.setCharacterEncoding("utf-8"); +// response.setStatus(HttpStatus.UNAUTHORIZED.value()); +// response.setContentType(MediaType.APPLICATION_JSON_VALUE); +// response.getWriter().write(objectMapper.writeValueAsString(Response.builder)); +// } } From 9b487d7e58145f7d3affc0b27e787505fe6974b6 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 10:16:40 +0900 Subject: [PATCH 059/123] =?UTF-8?q?feat=20:=20jwt=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=EC=A4=91=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/filter/JwtFilter.java | 40 +++------- .../example/onederful/security/JwtUtil.java | 77 +++++++++++-------- 2 files changed, 55 insertions(+), 62 deletions(-) diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java index 8f97ba7..5086987 100644 --- a/src/main/java/com/example/onederful/filter/JwtFilter.java +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -1,19 +1,11 @@ package com.example.onederful.filter; import com.example.onederful.security.JwtUtil; -import com.fasterxml.jackson.databind.ObjectMapper; -import io.jsonwebtoken.ExpiredJwtException; -import io.jsonwebtoken.MalformedJwtException; -import io.jsonwebtoken.UnsupportedJwtException; -import io.jsonwebtoken.security.SecurityException; -import io.jsonwebtoken.security.SignatureException; import jakarta.servlet.*; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.http.HttpStatus; -import org.springframework.http.MediaType; import java.io.IOException; import java.time.OffsetDateTime; @@ -52,27 +44,20 @@ public void doFilter( // "Bearer" 빼고 확인 String jwt = authorizationHeader.substring(7); - - // 토큰 검증 유무 확인 (응답 형태가 올바르지 못한 상태) - try { - jwtUtil.validateToken(jwt); - } - catch (SignatureException e) { - errorResponse(response, HttpServletResponse.SC_FORBIDDEN, "유효하지 않은 JWT 서명입니다."); - } catch (SecurityException | MalformedJwtException e){ - errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"잘못된 JWT 토큰 형식입니다."); - }catch (ExpiredJwtException e){ - errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"Expired JWT token, 만료된 JWT token 입니다."); - }catch (UnsupportedJwtException e){ - errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"Unsupported JWT token, 지원되지 않는 JWT 토큰 입니다."); - }catch (IllegalArgumentException e){ - errorResponse(response,HttpServletResponse.SC_FORBIDDEN,"JWT claims is empty, 잘못된 JWT 토큰 입니다."); + +// // 토큰 검증 + String errorMessage = jwtUtil.validateToken(jwt); + if (errorMessage != null) { + errorResponse(response, HttpServletResponse.SC_FORBIDDEN, errorMessage); + return; } + filterChain.doFilter(servletRequest,servletResponse); } + // 공통 에러 응답 처리 private void errorResponse(HttpServletResponse response, int status, String message) throws IOException { response.setStatus(status); response.setContentType("application/json;charset=utf-8"); @@ -87,11 +72,4 @@ private void errorResponse(HttpServletResponse response, int status, String mess response.getWriter().write(json); } -// private void errorResponse(HttpServletResponse response, String message) throws IOException{ -// ObjectMapper objectMapper = new ObjectMapper(); -// response.setCharacterEncoding("utf-8"); -// response.setStatus(HttpStatus.UNAUTHORIZED.value()); -// response.setContentType(MediaType.APPLICATION_JSON_VALUE); -// response.getWriter().write(objectMapper.writeValueAsString(Response.builder)); -// } -} +} \ No newline at end of file diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java index 62c6f02..e3b1a93 100644 --- a/src/main/java/com/example/onederful/security/JwtUtil.java +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -1,30 +1,33 @@ package com.example.onederful.security; import com.example.onederful.domain.user.entity.User; -import io.jsonwebtoken.Claims; -import io.jsonwebtoken.Jwts; -import io.jsonwebtoken.SignatureAlgorithm; +import io.jsonwebtoken.*; import io.jsonwebtoken.security.Keys; +import io.jsonwebtoken.security.SecurityException; import jakarta.annotation.PostConstruct; import jakarta.servlet.http.HttpServletRequest; -import java.security.Key; -import java.util.Base64; -import java.util.Date; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +import java.security.Key; +import java.util.Base64; +import java.util.Date; + @Slf4j @Component public class JwtUtil { // JWT Token 접두사 public final static String BEARER_PREFIX = "Bearer "; - // JWT 서명 알고리즘 - private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; + // JWT Token 만료시간 @Value("${jwt.expiration}") public Long expirationTime; + + // JWT 서명 알고리즘 + private final SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; + // 비밀 키 @Value("${jwt.secret.key}") private String secretKey; @@ -34,69 +37,77 @@ public class JwtUtil { /** - * 빈 초기화 메서드 - 애플리케이션 실행 시 비밀키를 Base64로 디코딩 하여 key 객체를 초기화 + * 빈 초기화 메서드 + * - 애플리케이션 실행 시 비밀키를 Base64로 디코딩 하여 key 객체를 초기화 */ @PostConstruct - public void init() { - byte[] bytes = Base64.getDecoder().decode(secretKey); + public void init(){ + byte [] bytes = Base64.getDecoder().decode(secretKey); key = Keys.hmacShaKeyFor(bytes); } /** * JWT 토큰 생성 - * * @param user User Entity * @return 생성된 JWT 토큰 */ - public String generateToken(User user) { + public String generateToken(User user){ Long id = user.getId(); String username = user.getUsername(); Date date = new Date(); return BEARER_PREFIX + - Jwts.builder() - .setSubject(username) - .claim("id", id) - .setIssuedAt(date) - .setExpiration(new Date(date.getTime() + expirationTime)) - .signWith(key, signatureAlgorithm) - .compact(); + Jwts.builder() + .setSubject(username) + .claim("id",id) + .setIssuedAt(date) + .setExpiration(new Date(date.getTime()+ expirationTime)) + .signWith(key,signatureAlgorithm) + .compact(); } /** * JWT 토큰 유효성 검증 - * * @param token JWT 토큰 * @return 토큰의 유효성 여부 (true : 유효, false : 유효하지 않음) */ - public void validateToken(String token){ + public String validateToken(String token){ + try { Jwts.parserBuilder() .setSigningKey(key) .build() .parseClaimsJws(token); + return null; // 유효함 + } catch (SecurityException | MalformedJwtException e) { + return "유효하지 않은 JWT 서명입니다."; + } catch (ExpiredJwtException e) { + return "만료된 JWT 토큰입니다."; + } catch (UnsupportedJwtException e) { + return "지원되지 않는 JWT 토큰입니다."; + } catch (IllegalArgumentException e) { + return "잘못된 JWT 토큰입니다."; + } } /** * Token에 존재하는 모든 클레임(페이로드 값)을 추출 - * * @param token 검증된 JWT 토큰 (로그인 한 상태) * @return 클라임 객체 */ - public Claims extractAllClaims(String token) { + public Claims extractAllClaims(String token){ return Jwts.parserBuilder() - .setSigningKey(key) - .build() - .parseClaimsJws(token) - .getBody(); + .setSigningKey(key) + .build() + .parseClaimsJws(token) + .getBody(); } /** * Token에 저장된 ID(기본키) 가져오기 - * - * @param request 인증 완료 HttpServletRequest + * @param request Request * @return ID값 */ public Long extractId(HttpServletRequest request) { @@ -104,4 +115,8 @@ public Long extractId(HttpServletRequest request) { String token = authorizationHeader.substring(7); return extractAllClaims(token).get("id", Long.class); } -} + + + + +} \ No newline at end of file From b79b7433982ad6d5a39a91a5b367bbb48f304802 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 11:09:22 +0900 Subject: [PATCH 060/123] =?UTF-8?q?fix:=20=EC=98=88=EC=99=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20=ED=86=B5=EC=9D=BC,=20=EB=86=93=EC=B9=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8/=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 2 +- .../comment/dto/CommentResponseDataDto.java | 5 +++- .../comment/repository/CommentRepository.java | 5 +++- .../comment/service/CommentService.java | 28 ++++++++++++------- .../onederful/exception/ErrorCode.java | 11 +++++++- 5 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 9471b13..89240cc 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -34,7 +34,7 @@ public ResponseEntity> updateComment( @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody UpdateCommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { UpdateCommentResponseDataDto updateCommentResponseDataDto = - commentService.updateComment(comment_id, requestDto.getContent(), httpServletRequest); + commentService.updateComment(task_id, comment_id, requestDto.getContent(), httpServletRequest); return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java index 90905a4..6833feb 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java @@ -10,11 +10,13 @@ public class CommentResponseDataDto { private final String writer; private final String content; + private final Long comment_id; private final LocalDateTime createdAt; private final LocalDateTime updatedAt; - public CommentResponseDataDto(String writer, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { + public CommentResponseDataDto(Long comment_id, String writer, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { + this.comment_id = comment_id; this.writer = writer; this.content = content; this.createdAt = createdAt; @@ -23,6 +25,7 @@ public CommentResponseDataDto(String writer, String content, LocalDateTime creat public static CommentResponseDataDto from(Comment comment){ return new CommentResponseDataDto( + comment.getId(), comment.getUser().getName(), comment.getContent(), comment.getCreatedAt(), diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java index 068b3b9..6acb12d 100644 --- a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -2,6 +2,8 @@ import com.example.onederful.domain.comment.entity.Comment; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import java.util.List; @@ -9,5 +11,6 @@ public interface CommentRepository extends JpaRepository { List findAllByTaskIdOrderByCreatedAtDesc(Long taskId); - List findBycontentLike(String content); + @Query("SELECT c from Comment c WHERE(c.content LIKE %:keyword% OR c.user.username LIKE %:keyword%) AND c.isDeleted = false") + List findByContentOrUsername(@Param("keyword") String keyword); } diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 8dd2473..e498e18 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -10,6 +10,8 @@ import com.example.onederful.domain.task.repository.TaskRepository; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.exception.CustomException; +import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; @@ -34,10 +36,10 @@ public CreateCommentResponseDataDto save(Long task_id, HttpServletRequest httpSe Long user_id = jwtUtil.extractId(httpServletRequest); User user = userRepository.findById(user_id) - .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); Task task = taskRepository.findById(task_id) - .orElseThrow(() -> new IllegalArgumentException("테스크를 찾을 수 없습니다.")); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); Comment comment = new Comment(content, user, task); Comment savedComment = commentRepository.save(comment); @@ -47,26 +49,32 @@ public CreateCommentResponseDataDto save(Long task_id, HttpServletRequest httpSe } @Transactional - public UpdateCommentResponseDataDto updateComment(Long comment_id, String content, HttpServletRequest httpServletRequest) { + public UpdateCommentResponseDataDto updateComment(Long task_id, Long comment_id, String content, HttpServletRequest httpServletRequest) { + Task task = taskRepository.findById(task_id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + Comment comment = commentRepository.findById(comment_id) - .orElseThrow(() ->new IllegalArgumentException("댓글을 찾을 수 없습니다.")); + .orElseThrow(() ->new CustomException(ErrorCode.NONEXISTENT_COMMENT)); // 토큰에서 Id 가져오기 Long userId = jwtUtil.extractId(httpServletRequest); User user = userRepository.findById(userId) - .orElseThrow(() -> new IllegalArgumentException("사용자를 찾을 수 없습니다.")); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); if(comment.getIsDeleted()==true){ - throw new IllegalArgumentException("삭제된 댓글입니다."); + throw new CustomException(ErrorCode.INVALID_COMMENT); } comment.update(content); return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContent(),comment.getCreatedAt(), comment.getUpdatedAt()); } - public List findAllCommentByTaskId(Long taskId){ - List commentListById = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(taskId); + public List findAllCommentByTaskId(Long task_id){ + Task task = taskRepository.findById(task_id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + + List commentListById = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(task_id); return commentListById.stream() .filter(comment -> !comment.getIsDeleted()) @@ -77,7 +85,7 @@ public List findAllCommentByTaskId(Long taskId){ public List findCommentByContent(String content){ - List commentListByContent = commentRepository.findBycontentLike("%"+content+"%"); + List commentListByContent = commentRepository.findByContentOrUsername("%"+content+"%"); return commentListByContent.stream() .filter(comment -> !comment.getIsDeleted()) @@ -89,7 +97,7 @@ public List findCommentByContent(String content){ @Transactional public void deleteComment(Long commentId){ Comment comment = commentRepository.findById(commentId) - .orElseThrow(() ->new IllegalArgumentException("댓글을 찾을 수 없습니다.")); + .orElseThrow(() ->new CustomException(ErrorCode.NONEXISTENT_COMMENT)); comment.delete(); } diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index e263aac..974e9c1 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -7,11 +7,20 @@ @AllArgsConstructor @Getter public enum ErrorCode { + // User DUPLICATE_USER(HttpStatus.CONFLICT,"이미 존재하는 사용자입니다."), BAD_REQUEST(HttpStatus.BAD_REQUEST,"잘못된 사용자명 또는 비밀번호입니다."), UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"인증이 필요합니다."), INVALID_PASSWORD(HttpStatus.UNAUTHORIZED,"비밀번호가 일치하지 않습니다."), - LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."); + LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."), + + + // Comment + NONEXISTENT_USER(HttpStatus.BAD_REQUEST, "존재하지 않는 사용자입니다."), + NONEXISTENT_TASK(HttpStatus.BAD_REQUEST, "존재하지 않는 테스크입니다."), + NONEXISTENT_COMMENT(HttpStatus.BAD_REQUEST, "존재하지 않는 댓글입니다."), + INVALID_COMMENT(HttpStatus.BAD_REQUEST, "삭제된 댓글입니다."); + private final HttpStatus status; private final String message; From 8a8a885bc5967342a80d555b59d8edba200510a0 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 11:11:55 +0900 Subject: [PATCH 061/123] =?UTF-8?q?squash!=20fix:=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20=ED=86=B5=EC=9D=BC,=20=EB=86=93=EC=B9=9C?= =?UTF-8?q?=20=EC=98=88=EC=99=B8/=EC=A1=B0=EA=B1=B4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/domain/comment/service/CommentService.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index e498e18..6484d96 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -85,6 +85,7 @@ public List findAllCommentByTaskId(Long task_id){ public List findCommentByContent(String content){ + // 찾는 내용을 댓글을 적은 사람과 댓글 내용에서 검색 List commentListByContent = commentRepository.findByContentOrUsername("%"+content+"%"); return commentListByContent.stream() From 4ddfac6f75cde7aaedb98af48de32a2a33a7ad03 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 11:58:29 +0900 Subject: [PATCH 062/123] =?UTF-8?q?chore:=20queryDSL=20dependency=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 --- build.gradle | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.gradle b/build.gradle index 22f4c2e..18184a1 100644 --- a/build.gradle +++ b/build.gradle @@ -43,8 +43,18 @@ dependencies { // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' + + //QueryDDL 추가 + implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' + annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" + annotationProcessor "jakarta.annotation:jakarta.annotation-api" + annotationProcessor "jakarta.persistence:jakarta.persistence-api" } tasks.named('test') { useJUnitPlatform() } + +clean { + delete file('src/main/generated') +} \ No newline at end of file From 2955b5a96148c3177fd8154e0d2a6e3a0fe03ecc Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 11:59:46 +0900 Subject: [PATCH 063/123] =?UTF-8?q?chore:=20queryDSL=20dependency=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 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 18184a1..7f1b5b3 100644 --- a/build.gradle +++ b/build.gradle @@ -44,7 +44,7 @@ dependencies { // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' - //QueryDDL 추가 + //QueryDsL 추가 implementation 'com.querydsl:querydsl-jpa:5.0.0:jakarta' annotationProcessor "com.querydsl:querydsl-apt:${dependencyManagement.importedProperties['querydsl.version']}:jakarta" annotationProcessor "jakarta.annotation:jakarta.annotation-api" From cd5fcfc6d46e8eb7604ae97c20e36616d31c7b7f Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 12:00:27 +0900 Subject: [PATCH 064/123] =?UTF-8?q?feat:=20UserNotFound=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/onederful/exception/ErrorCode.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index e263aac..f7e2d76 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -11,7 +11,9 @@ public enum ErrorCode { BAD_REQUEST(HttpStatus.BAD_REQUEST,"잘못된 사용자명 또는 비밀번호입니다."), UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"인증이 필요합니다."), INVALID_PASSWORD(HttpStatus.UNAUTHORIZED,"비밀번호가 일치하지 않습니다."), - LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."); + LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."), + + USER_NOT_EXIST(HttpStatus.NOT_FOUND, "존재하지 않는 유저입니다."); private final HttpStatus status; private final String message; From b337891497c930a1585ffabb738975498b02eda9 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 12:01:14 +0900 Subject: [PATCH 065/123] =?UTF-8?q?feat:=20dashboard=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4=EB=9F=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DashboardController.java | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java diff --git a/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java b/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java new file mode 100644 index 0000000..4a81430 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java @@ -0,0 +1,55 @@ +package com.example.onederful.domain.dashboard.controller; + +import com.example.onederful.domain.dashboard.dto.ApiResponse; +import com.example.onederful.domain.dashboard.dto.MyTasksTodayResponseDto; +import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; +import com.example.onederful.domain.dashboard.service.DashboardService; +import com.example.onederful.security.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; +import lombok.RequiredArgsConstructor; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +@RestController +@RequestMapping("/api/dashboard") +@RequiredArgsConstructor +public class DashboardController { + + private final DashboardService dashboardService; + private final JwtUtil jwtUtil; + + @GetMapping("/statistics") + public ResponseEntity> getStatistics(){ + StatisticsResponseDto data = dashboardService.getStatistics(); + + return new ResponseEntity<>( + ApiResponse.success( + "통계정보를 조회했습니다.", + data + ), + HttpStatus.OK + ); + } + + @GetMapping("/my-tasks-today") + public ResponseEntity>> getMyTasksToday( + HttpServletRequest request + ){ + Long userId = jwtUtil.extractId(request); + + List data = dashboardService.getMyTasksToday(userId); + + return new ResponseEntity<>( + ApiResponse.success( + "오늘 내 태스크 정보를 조회했습니다.", + data + ), + HttpStatus.OK + ); + } +} From 9f4ef36ae370bf67158ab1560e1513def29abb36 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 12:01:40 +0900 Subject: [PATCH 066/123] =?UTF-8?q?feat:=20dashboard=20=EB=A0=88=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/DashboardRepository.java | 12 ++ .../repository/DashboardRepositoryImpl.java | 117 ++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepository.java create mode 100644 src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java diff --git a/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepository.java b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepository.java new file mode 100644 index 0000000..d89c9b6 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepository.java @@ -0,0 +1,12 @@ +package com.example.onederful.domain.dashboard.repository; + +import com.example.onederful.domain.dashboard.dto.MyTasksTodayResponseDto; +import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; +import com.example.onederful.domain.task.entity.Task; + +import java.util.List; + +public interface DashboardRepository { + StatisticsResponseDto getStatistics(); + List getMyTasksToday(Long userId); +} diff --git a/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java new file mode 100644 index 0000000..fea4c3e --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java @@ -0,0 +1,117 @@ +package com.example.onederful.domain.dashboard.repository; + +import com.example.onederful.domain.dashboard.dto.MyTasksTodayResponseDto; +import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; +import com.example.onederful.domain.task.entity.QTask; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.querydsl.jpa.impl.JPAQueryFactory; +import jakarta.persistence.EntityManager; +import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + + +@Repository +public class DashboardRepositoryImpl implements DashboardRepository { + + private final JPAQueryFactory queryFactory; + + public DashboardRepositoryImpl(EntityManager em){ + this.queryFactory = new JPAQueryFactory(em); + } + + QTask task; + + @Override + public StatisticsResponseDto getStatistics(){ + + task = QTask.task; + + Long total = Optional.ofNullable( + queryFactory + .select(task.count()) + .from(task) + .where(task.isDeleted.isFalse()) + .fetchOne() + ).orElse(0L); + + Long todo = Optional.ofNullable( + queryFactory + .select(task.count()) + .from(task) + .where( + task.status.eq(ProcessStatus.TODO), + task.isDeleted.isFalse() + ) + .fetchOne() + ).orElse(0L);; + + Long inProgress = Optional.ofNullable( + queryFactory + .select(task.count()) + .from(task) + .where( + task.status.eq(ProcessStatus.IN_PROGRESS), + task.isDeleted.isFalse() + ) + .fetchOne() + ).orElse(0L); + + Long done = Optional.ofNullable( + queryFactory + .select(task.count()) + .from(task) + .where( + task.status.eq(ProcessStatus.DONE), + task.isDeleted.isFalse() + ) + .fetchOne() + ).orElse(0L); + + Long overdue = Optional.ofNullable( + queryFactory + .select(task.count()) + .from(task) + .where( + task.isDeleted.isFalse(), + task.status.in(ProcessStatus.TODO, ProcessStatus.IN_PROGRESS), + task.dueDate.before(LocalDateTime.now()) + ) + .fetchOne() + ).orElse(0L); + + double taskDoneRate = 0.0; + if(total != 0L){ + taskDoneRate = (double) done / total * 100; + } + + return StatisticsResponseDto.builder() + .totalTaskCount(total) + .todoTaskCount(todo) + .inProgressTaskCount(inProgress) + .doneTaskCount(done) + .taskDoneRate(taskDoneRate) + .overdueTaskCount(overdue) + .build(); + } + + @Override + public List getMyTasksToday(Long userId){ + task = QTask.task; + + List taskList = queryFactory + .select(task) + .from(task) + .where( + task.assignee.id.eq(userId), + task.isDeleted.isFalse(), + task.status.in(ProcessStatus.TODO, ProcessStatus.IN_PROGRESS) + ) + .orderBy(task.priority.desc()) + .fetch(); + + return taskList; + } +} From 2fbd9bb3ca7bb4a5069963e53369d59cbef7c4c6 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 12:02:03 +0900 Subject: [PATCH 067/123] =?UTF-8?q?feat:=20dashboard=20=EC=84=9C=EB=B9=84?= =?UTF-8?q?=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dashboard/service/DashboardService.java | 52 +++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java diff --git a/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java b/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java new file mode 100644 index 0000000..2bd4d92 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java @@ -0,0 +1,52 @@ +package com.example.onederful.domain.dashboard.service; + +import com.example.onederful.domain.dashboard.dto.MyTasksTodayResponseDto; +import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; +import com.example.onederful.domain.dashboard.repository.DashboardRepository; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.exception.CustomException; +import com.example.onederful.exception.ErrorCode; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +@Service +@RequiredArgsConstructor +public class DashboardService { + private final DashboardRepository dashboardRepository; + private final UserRepository userRepository; + + public StatisticsResponseDto getStatistics(){ + + return dashboardRepository.getStatistics(); + } + + public List getMyTasksToday(Long userId){ + + userRepository.findById(userId).orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_EXIST)); + + List tasks = dashboardRepository.getMyTasksToday(userId); + List dtos = tasks.stream() + .map(t -> MyTasksTodayResponseDto.builder() + .id(t.getId()) + .title(t.getTitle()) + .contents(t.getDescription()) + .priority(t.getPriority()) + .managerId(t.getAssignee().getId()) + .userId(t.getUser().getId()) + .deadline(t.getDueDate()) + .status(t.getStatus()) + .started_at(t.getStartedAt()) + .created_at(t.getCreatedAt()) + .updated_at(t.getUpdatedAt()) + .build() + ) + .toList(); + + return dtos; + } +} From 296e1a4b6d1cd7f21e11664db05523c9f59bd7ba Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 12:02:41 +0900 Subject: [PATCH 068/123] =?UTF-8?q?feat:=20dashboard=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20dto=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dashboard/dto/ApiResponse.java | 39 +++++++++++++++++++ .../dto/MyTasksTodayResponseDto.java | 38 ++++++++++++++++++ .../dashboard/dto/StatisticsResponseDto.java | 22 +++++++++++ 3 files changed, 99 insertions(+) create mode 100644 src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java create mode 100644 src/main/java/com/example/onederful/domain/dashboard/dto/MyTasksTodayResponseDto.java create mode 100644 src/main/java/com/example/onederful/domain/dashboard/dto/StatisticsResponseDto.java diff --git a/src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java b/src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java new file mode 100644 index 0000000..65adba8 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java @@ -0,0 +1,39 @@ +package com.example.onederful.domain.dashboard.dto; + +import com.fasterxml.jackson.annotation.JsonFormat; +import lombok.Getter; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.time.OffsetDateTime; + +@Getter +@NoArgsConstructor +public class ApiResponse { + + private boolean success;// API 호출 성공/실패 여부 + private String message;// 사용자에게 보여줄 메시지 + private T data;// 실제 데이터 (제네릭 타입) + + // JSON으로 변환될 때 날짜 형식을 지정 + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'") + private OffsetDateTime timestamp;// 응답 시간 + + // 전체 필드를 초기화하는 생성자 + private ApiResponse(boolean success, String message, T data) { + this.success = success; + this.message = message; + this.data = data; + this.timestamp = OffsetDateTime.now();// 현재 시간으로 자동 설정 + } + + // 성공 응답을 쉽게 만들어주는 static 메서드 + public static ApiResponse success(String message, T data) { + return new ApiResponse<>(true, message, data); + } + + // 실패 응답을 쉽게 만들어주는 static 메서드 + public static ApiResponse error(String message) { + return new ApiResponse<>(false, message, null); + } +} diff --git a/src/main/java/com/example/onederful/domain/dashboard/dto/MyTasksTodayResponseDto.java b/src/main/java/com/example/onederful/domain/dashboard/dto/MyTasksTodayResponseDto.java new file mode 100644 index 0000000..bec39bc --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/dto/MyTasksTodayResponseDto.java @@ -0,0 +1,38 @@ +package com.example.onederful.domain.dashboard.dto; + +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.querydsl.core.annotations.QueryProjection; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +import java.time.LocalDateTime; + +@Getter +@Builder +public class MyTasksTodayResponseDto { + + private final Long id; + + private final String title; + + private final String contents; + + private final Priority priority; + + private final Long managerId; + + private final Long userId; + + private final LocalDateTime deadline; + + private final ProcessStatus status; + + private final LocalDateTime started_at; + + private final LocalDateTime created_at; + + private final LocalDateTime updated_at; + +} diff --git a/src/main/java/com/example/onederful/domain/dashboard/dto/StatisticsResponseDto.java b/src/main/java/com/example/onederful/domain/dashboard/dto/StatisticsResponseDto.java new file mode 100644 index 0000000..a72efe1 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/dashboard/dto/StatisticsResponseDto.java @@ -0,0 +1,22 @@ +package com.example.onederful.domain.dashboard.dto; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class StatisticsResponseDto { + + private final Long totalTaskCount; + + private final Long todoTaskCount; + + private final Long inProgressTaskCount; + + private final Long doneTaskCount; + + private final Double taskDoneRate; + + private final Long overdueTaskCount; + +} From acd00b04817d7452aa070b90719ee5742e96b25c Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 12:13:04 +0900 Subject: [PATCH 069/123] =?UTF-8?q?refactor=20:=20NullpointerException=20?= =?UTF-8?q?=EB=B0=A9=EC=A7=80=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/onederful/security/JwtUtil.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/com/example/onederful/security/JwtUtil.java b/src/main/java/com/example/onederful/security/JwtUtil.java index e3b1a93..73ec59e 100644 --- a/src/main/java/com/example/onederful/security/JwtUtil.java +++ b/src/main/java/com/example/onederful/security/JwtUtil.java @@ -112,6 +112,9 @@ public Claims extractAllClaims(String token){ */ public Long extractId(HttpServletRequest request) { String authorizationHeader = request.getHeader("Authorization"); + if (authorizationHeader == null || !authorizationHeader.startsWith("Bearer ")) { + return null; // 로그인 안 된 상태면 null + } String token = authorizationHeader.substring(7); return extractAllClaims(token).get("id", Long.class); } From 2c24e5688ca8277ab8336e7564fe7107e10ef28b Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 12:22:44 +0900 Subject: [PATCH 070/123] =?UTF-8?q?fix:=20my-tasks-today=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20=EC=A0=95=EB=A0=AC=20=EA=B8=B0=EB=8A=A5?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/DashboardRepositoryImpl.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java index fea4c3e..4ca0c4e 100644 --- a/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java +++ b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java @@ -4,13 +4,17 @@ import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; import com.example.onederful.domain.task.entity.QTask; import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.Priority; import com.example.onederful.domain.task.enums.ProcessStatus; import com.querydsl.jpa.impl.JPAQueryFactory; import jakarta.persistence.EntityManager; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; +import java.util.Comparator; import java.util.List; +import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; @Repository @@ -100,6 +104,11 @@ public StatisticsResponseDto getStatistics(){ @Override public List getMyTasksToday(Long userId){ task = QTask.task; + Map priority = Map.of( + Priority.HIGH, 0, + Priority.MEDIUM, 1, + Priority.LOW, 2 + ); List taskList = queryFactory .select(task) @@ -109,9 +118,11 @@ public List getMyTasksToday(Long userId){ task.isDeleted.isFalse(), task.status.in(ProcessStatus.TODO, ProcessStatus.IN_PROGRESS) ) - .orderBy(task.priority.desc()) .fetch(); + List sortedTaskList = taskList.stream() + .sorted(Comparator.comparing(task -> priority.get(task.getPriority()))) + .collect(Collectors.toList()); - return taskList; + return sortedTaskList; } } From b516389124bdd1636be3971bd2f365831cb09b00 Mon Sep 17 00:00:00 2001 From: saevit Date: Wed, 18 Jun 2025 12:41:43 +0900 Subject: [PATCH 071/123] =?UTF-8?q?feat:=20user=20=EB=A1=9C=EA=B7=B8?= =?UTF-8?q?=EC=9D=B8=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=20=EA=B8=B0=EB=A1=9D?= =?UTF-8?q?=EB=90=98=EB=A1=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/LoggingAspect.java | 21 ++++++--- .../onederful/domain/log/enums/Activity.java | 10 ++-- .../domain/log/service/LogService.java | 47 ++++++++++++++++++- 3 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index 7a14953..f27541c 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -1,6 +1,5 @@ package com.example.onederful.domain.log; -import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; @@ -25,19 +24,18 @@ public class LoggingAspect { ) public void cudMethods() {} - @Pointcut("execution(* com.example..userService.login())") - public void loginMethods() {} + @Pointcut("execution(* com.example..UserService.login(..))") + public void loginMethod() {} // 생성, 수정, 삭제 @AfterReturning(pointcut = "cudMethods()", returning = "result") - public void logCudMethods(JoinPoint joinPoint, Object result) { - System.out.println("메서드 정상 실행 후: 로그 기록"); + public void logCudMethods(Object result) { - // HttpServletRequest으로부터 요청 ip, 메서드, url + // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userid HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); // 로그 저장 - logService.saveLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), result); + logService.saveCudLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), result); } // 상태 변경 @@ -56,5 +54,14 @@ public void logCudMethods(JoinPoint joinPoint, Object result) { // } // 로그인/로그아웃 + @AfterReturning(pointcut = "loginMethod()", returning = "result") + public void logLoginMethod(Object result) { + System.out.println("메서드 정상 실행 후: 로그 기록"); + + // HttpServletRequest으로부터 요청 ip, 메서드, url + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + // 로그 저장 + logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); + } } diff --git a/src/main/java/com/example/onederful/domain/log/enums/Activity.java b/src/main/java/com/example/onederful/domain/log/enums/Activity.java index 929cb54..eef3197 100644 --- a/src/main/java/com/example/onederful/domain/log/enums/Activity.java +++ b/src/main/java/com/example/onederful/domain/log/enums/Activity.java @@ -3,14 +3,14 @@ public enum Activity { TASK_CREATED("새로운 작업이 생성되었습니다."), TASK_UPDATED("작업이 수정되었습니다."), - TASK_DELETED("작업이 삭제되었습니다."); - // TASK_STATUS_TODO_TO_IN_PROGRESS, - // TASK_STATUS_IN_PROGRESS_TO_DONE, - // TASK_STATUS_TODO_TO_DONE, + TASK_DELETED("작업이 삭제되었습니다."), + TASK_STATUS_TODO_TO_IN_PROGRESS("작업이 TODO에서 IN_PROGRESS로 변경되었습니다."), + TASK_STATUS_IN_PROGRESS_TO_DONE("작업이 IN_PROGRESS에서 DONE으로 변경되었습니다."), + TASK_STATUS_TODO_TO_DONE("작업이 TODO에서 DONE으로 변경되었습니다."), // COMMENT_CREATED, // COMMENT_UPDATED, // COMMENT_DELETED, - // USER_LOGGED_IN("로그인 하였습니다."), + USER_LOGGED_IN("로그인 하였습니다."); // USER_LOGGED_OUT("로그아웃 하였습니다.") private final String logMessage; diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index f7043e3..f9d3e51 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -14,10 +14,13 @@ import com.example.onederful.domain.log.repository.LogRepository; import com.example.onederful.domain.log.repository.LogSpecification; import com.example.onederful.domain.task.dto.response.TaskResponse; +import com.example.onederful.domain.user.dto.ApiResponseDto; +import com.example.onederful.domain.user.dto.Tokeninfo; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; import com.example.onederful.exception.CustomException; import com.example.onederful.exception.ErrorCode; +import com.example.onederful.security.JwtUtil; import jakarta.transaction.Transactional; import lombok.RequiredArgsConstructor; @@ -28,6 +31,7 @@ public class LogService { private final LogRepository logRepository; private final UserRepository userRepositry; + private final JwtUtil jwtUtil; public Page getLog( Long userId, String activityStr, Long targetId, @@ -46,7 +50,7 @@ public Page getLog( } @Transactional - public void saveLog(String ip, Method method, String url, Long userId, Object result) { + public void saveCudLog(String ip, Method method, String url, Long userId, Object result) { // 현재 유저 조회 User user = userRepositry.findById(userId).orElseThrow( () -> new CustomException(ErrorCode.UNAUTHORIZED) @@ -81,6 +85,47 @@ else if (method.equals(Method.DELETE) && url.contains("/tasks")) { // if (targetId == null) 예외 처리 + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } + + @Transactional + public void saveLoginLog(String ip, Method method, String url, Object result) { + // userId + Long userId = null; + if (result instanceof ApiResponseDto) { + Object data = ((ApiResponseDto) result).getData(); + if (data instanceof Tokeninfo) { + String token = ((Tokeninfo) data).getToken(); + userId = jwtUtil.extractAllClaims(token).get("id", Long.class); + } + } + + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + // 활동 유형 + Activity activity = Activity.USER_LOGGED_IN; + + // if (activity == null) 예외 처리 + + // 대상 id + Long targetId = userId; + + // if (targetId == null) 예외 처리 + + // 로그 DB에 저장 Log log = Log.builder() .user(user) .activity(activity) From de6991a84e81a6faec9a28bc512e782ddacffd63 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 14:20:19 +0900 Subject: [PATCH 072/123] =?UTF-8?q?chore=20:=20H2=20=EC=9D=B8=EB=A9=94?= =?UTF-8?q?=EB=AA=A8=EB=A6=AC=20DB=20=EC=9D=98=EC=A1=B4=EC=84=B1=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 --- build.gradle | 63 +++++++++++++++++++++++++++------------------------- 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/build.gradle b/build.gradle index 22f4c2e..0c2a68e 100644 --- a/build.gradle +++ b/build.gradle @@ -1,50 +1,53 @@ plugins { - id 'java' - id 'org.springframework.boot' version '3.5.0' - id 'io.spring.dependency-management' version '1.1.7' + id 'java' + id 'org.springframework.boot' version '3.5.0' + id 'io.spring.dependency-management' version '1.1.7' } group = 'com.example' version = '0.0.1-SNAPSHOT' java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } + toolchain { + languageVersion = JavaLanguageVersion.of(17) + } } configurations { - compileOnly { - extendsFrom annotationProcessor - } + compileOnly { + extendsFrom annotationProcessor + } } repositories { - mavenCentral() + mavenCentral() } dependencies { - implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation 'org.springframework.boot:spring-boot-starter-validation' - implementation 'org.springframework.boot:spring-boot-starter-web' - compileOnly 'org.projectlombok:lombok' - runtimeOnly 'com.mysql:mysql-connector-j' - annotationProcessor 'org.projectlombok:lombok' - testImplementation 'org.springframework.boot:spring-boot-starter-test' - testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - - // JWT - implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' - runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' - runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' - - // bcrypt - implementation 'at.favre.lib:bcrypt:0.10.2' - - // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 - implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' + implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation 'org.springframework.boot:spring-boot-starter-validation' + implementation 'org.springframework.boot:spring-boot-starter-web' + compileOnly 'org.projectlombok:lombok' + runtimeOnly 'com.mysql:mysql-connector-j' + annotationProcessor 'org.projectlombok:lombok' + testImplementation 'org.springframework.boot:spring-boot-starter-test' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + + // JWT + implementation group: 'io.jsonwebtoken', name: 'jjwt-api', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-impl', version: '0.11.5' + runtimeOnly group: 'io.jsonwebtoken', name: 'jjwt-jackson', version: '0.11.5' + + // bcrypt + implementation 'at.favre.lib:bcrypt:0.10.2' + + // OffsetDateTime 역직렬화 하기 위해 필요한 모듈 + implementation 'com.fasterxml.jackson.datatype:jackson-datatype-jsr310' + + // 테스트용 인메모리 DB + testImplementation 'com.h2database:h2' } tasks.named('test') { - useJUnitPlatform() + useJUnitPlatform() } From 90dbf73316ffa7439276de53a60e3d9959bdeddf Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 14:21:23 +0900 Subject: [PATCH 073/123] =?UTF-8?q?refactor=20:=20Task=20save=EC=8B=9C=20?= =?UTF-8?q?=EB=B0=98=ED=99=98=EA=B0=92=20=EC=B6=94=EA=B0=80=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EC=9E=91=EC=84=B1=20?= =?UTF-8?q?=EC=8B=9C=20save=20=EB=B0=98=ED=99=98=EA=B0=92=EC=9D=B4=20?= =?UTF-8?q?=EC=97=86=EB=8A=94=20=EB=AC=B8=EC=A0=9C=EB=A1=9C=20=EC=9D=B8?= =?UTF-8?q?=ED=95=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/domain/task/service/TaskService.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index 166fb97..dde64f6 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -34,7 +34,6 @@ public TaskResponse createTask(TaskSaveRequest request, HttpServletRequest httpS User me = userRepository.findById(userId).orElseThrow(); User manager = userRepository.findById(request.getAssigneeId()).orElseThrow(); - // user (생성한 사람은 추후 로그인 연동 후 수정 예정) Task task = Task.builder() .title(request.getTitle()) .description(request.getDescription()) @@ -45,9 +44,9 @@ public TaskResponse createTask(TaskSaveRequest request, HttpServletRequest httpS .dueDate(request.getDueDate().toLocalDateTime()) .build(); - taskRepository.save(task); + Task savedTask = taskRepository.save(task); - return TaskResponse.of(task); + return TaskResponse.of(savedTask); } @Transactional(readOnly = true) From 145a984a04e1c835244b606458e657ba56d75769 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 14:22:08 +0900 Subject: [PATCH 074/123] =?UTF-8?q?chore=20:=20test=20code=20yml=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/resources/application-test.yml | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/resources/application-test.yml diff --git a/src/test/resources/application-test.yml b/src/test/resources/application-test.yml new file mode 100644 index 0000000..9609027 --- /dev/null +++ b/src/test/resources/application-test.yml @@ -0,0 +1,20 @@ +spring: + datasource: + url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=false + driver-class-name: org.h2.Driver + username: test + password: + + jpa: + show-sql: true + hibernate: + ddl-auto: create-drop + database-platform: org.hibernate.dialect.H2Dialect + properties: + hibernate: + format_sql: true + show_sql: true + use_sql_comment: true + highlight_sql: true + + From e5ccc604b4a77e5ae6f494408b96c109f642f1c0 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 14:22:36 +0900 Subject: [PATCH 075/123] =?UTF-8?q?test=20:=20Task=20test=20code=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20Service=20Layer=20test=20code?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/task/service/TaskServiceTest.java | 338 ++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java diff --git a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java new file mode 100644 index 0000000..b8a1d3c --- /dev/null +++ b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java @@ -0,0 +1,338 @@ +package com.example.onederful.domain.task.service; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.verify; + +import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.request.TaskUpdateRequest; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.task.repository.TaskRepository; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.enums.Role; +import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.security.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; +import java.time.LocalDateTime; +import java.time.OffsetDateTime; +import java.util.List; +import java.util.Optional; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageImpl; +import org.springframework.data.domain.PageRequest; +import org.springframework.data.domain.Pageable; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.test.util.ReflectionTestUtils; + +@ExtendWith(MockitoExtension.class) +public class TaskServiceTest { + + @Mock + private TaskRepository taskRepository; + + @Mock + private UserRepository userRepository; + + @Mock + private JwtUtil jwtUtil; + + @InjectMocks + private TaskService taskService; + + @Test + @DisplayName("업무 생성이 성공한다.") + void 업무_생성_성공_테스트() { + //given + TaskSaveRequest request = new TaskSaveRequest("title", "description", Priority.LOW, + 1L, OffsetDateTime.parse("2027-04-02T23:59:59Z")); + HttpServletRequest httpServletRequest = new MockHttpServletRequest(); + + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + User manager = User.builder() + .id(userId) + .email("manager@example.com") + .name("manager") + .password("!@A12345") + .role(Role.USER) + .username("manager") + .build(); + + Task task = Task.builder() + .id(2L) + .title(request.getTitle()) + .description(request.getDescription()) + .priority(request.getPriority()) + .assignee(manager) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(request.getDueDate().toLocalDateTime()) + .build(); + + ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task, "updatedAt", LocalDateTime.now()); + + given(jwtUtil.extractId(any(HttpServletRequest.class))).willReturn(userId); + given(userRepository.findById(me.getId())).willReturn(Optional.of(me)); + given(userRepository.findById(manager.getId())).willReturn(Optional.of(manager)); + given(taskRepository.save(any(Task.class))).willReturn(task); + + //when + + taskService.createTask(request, httpServletRequest); + + //then + Assertions.assertEquals(task.getTitle(), request.getTitle()); + Assertions.assertEquals(task.getDescription(), request.getDescription()); + + verify(taskRepository).save(any(Task.class)); + } + + @Test + @DisplayName("업무 세부사항 조회가 성공한다.") + void 업무_조회_성공_테스트() { + //given + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + User manager = User.builder() + .id(userId) + .email("manager@example.com") + .name("manager") + .password("!@A12345") + .role(Role.USER) + .username("manager") + .build(); + + Task task = Task.builder() + .id(2L) + .title("test") + .description("description") + .priority(Priority.LOW) + .assignee(manager) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task, "updatedAt", LocalDateTime.now()); + + given(taskRepository.findById(anyLong())).willReturn(Optional.of(task)); + + //when + + taskService.findTask(anyLong()); + + //then + + Assertions.assertEquals("test", task.getTitle()); + Assertions.assertEquals("description", task.getDescription()); + + verify(taskRepository).findById(anyLong()); + } + + @Test + @DisplayName("업무 세부사항 조회가 성공한다.") + void 업무_리스트_조회_성공_테스트() { + //given + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + User manager = User.builder() + .id(userId) + .email("manager@example.com") + .name("manager") + .password("!@A12345") + .role(Role.USER) + .username("manager") + .build(); + + Task task1 = Task.builder() + .id(2L) + .title("test1") + .description("description1") + .priority(Priority.LOW) + .assignee(manager) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + Task task2 = Task.builder() + .id(2L) + .title("test2") + .description("description2") + .priority(Priority.LOW) + .assignee(manager) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + ReflectionTestUtils.setField(task1, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task1, "updatedAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task2, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task2, "updatedAt", LocalDateTime.now()); + + List list = List.of(task1, task2); + Page tasks = new PageImpl<>(list); + + Pageable pageable = PageRequest.of(0, 10); + String search = "test"; + ProcessStatus status = ProcessStatus.TODO; + + given(taskRepository.findTasks(search, status, pageable)).willReturn(tasks); + + //when + + taskService.findTasks(pageable, search, status); + + //then + Assertions.assertEquals(2, tasks.getTotalElements()); + Assertions.assertEquals(1, tasks.getTotalPages()); + + verify(taskRepository).findTasks(search, status, pageable); + } + + @Test + @DisplayName("업무 삭제가 성공한다.") + void 업무_삭제_성공_테스트() { + //given + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + User manager = User.builder() + .id(userId) + .email("manager@example.com") + .name("manager") + .password("!@A12345") + .role(Role.USER) + .username("manager") + .build(); + + Task task = Task.builder() + .id(2L) + .title("test") + .description("description") + .priority(Priority.LOW) + .assignee(manager) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task, "updatedAt", LocalDateTime.now()); + + given(taskRepository.findById(anyLong())).willReturn(Optional.of(task)); + + //when + + taskService.deleteTask(task.getId()); + + //then + + Assertions.assertTrue(task.getIsDeleted()); + } + + @Test + @DisplayName("업무 수정이 성공한다.") + void 업무_수정_성공_테스트() { + //given + + Long id = 1L; + + TaskUpdateRequest request = new TaskUpdateRequest("title", "description", Priority.MEDIUM, + 2L, ProcessStatus.IN_PROGRESS, OffsetDateTime.parse("2027-04-02T23:59:59Z")); + + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + User manager = User.builder() + .id(request.getAssigneeId()) + .email("manager@example.com") + .name("manager") + .password("!@A12345") + .role(Role.USER) + .username("manager") + .build(); + + Task task = Task.builder() + .id(2L) + .title("test") + .description("description") + .priority(Priority.LOW) + .assignee(me) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task, "updatedAt", LocalDateTime.now()); + + given(taskRepository.findById(anyLong())).willReturn(Optional.of(task)); + given(userRepository.findById(anyLong())).willReturn(Optional.of(manager)); + + //when + + taskService.updateTask(id, request); + + //then + + Assertions.assertEquals(task.getAssignee(), manager); + Assertions.assertEquals(ProcessStatus.IN_PROGRESS, task.getStatus()); + } +} From 5100bd80a9d6327e405ecb088248aaba6684a98d Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 15:21:27 +0900 Subject: [PATCH 076/123] =?UTF-8?q?refactor=20:=20=EC=A4=91=EB=B3=B5=20?= =?UTF-8?q?=EB=82=B4=EC=9A=A9=EC=9D=B4=20=EB=A7=8E=EC=9D=80=20DTO=20Group?= =?UTF-8?q?=ED=99=94=20create,=20update=20dto=20=EA=B7=B8=EB=A3=B9?= =?UTF-8?q?=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/task/common/CreateGroup.java | 5 +++ .../domain/task/common/UpdateGroup.java | 5 +++ .../task/controller/TaskController.java | 40 ++++++++----------- .../task/dto/request/TaskSaveRequest.java | 11 ++++- .../task/dto/request/TaskUpdateRequest.java | 34 ---------------- 5 files changed, 35 insertions(+), 60 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/task/common/CreateGroup.java create mode 100644 src/main/java/com/example/onederful/domain/task/common/UpdateGroup.java delete mode 100644 src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java diff --git a/src/main/java/com/example/onederful/domain/task/common/CreateGroup.java b/src/main/java/com/example/onederful/domain/task/common/CreateGroup.java new file mode 100644 index 0000000..e910e6d --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/common/CreateGroup.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.task.common; + +public interface CreateGroup { + +} diff --git a/src/main/java/com/example/onederful/domain/task/common/UpdateGroup.java b/src/main/java/com/example/onederful/domain/task/common/UpdateGroup.java new file mode 100644 index 0000000..452d884 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/common/UpdateGroup.java @@ -0,0 +1,5 @@ +package com.example.onederful.domain.task.common; + +public interface UpdateGroup { + +} diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java index e213d15..b3d402f 100644 --- a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -1,8 +1,9 @@ package com.example.onederful.domain.task.controller; +import com.example.onederful.common.ApiResponseDto; +import com.example.onederful.domain.task.common.CreateGroup; +import com.example.onederful.domain.task.common.UpdateGroup; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; -import com.example.onederful.domain.task.dto.request.TaskUpdateRequest; -import com.example.onederful.domain.task.dto.response.CommonResponse; import com.example.onederful.domain.task.dto.response.TaskResponse; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.service.TaskService; @@ -10,7 +11,6 @@ import jakarta.validation.Valid; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; -import java.time.OffsetDateTime; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.PageRequest; @@ -37,28 +37,25 @@ public class TaskController { private final TaskService taskService; @PostMapping - public ResponseEntity> createTask( - @RequestBody @Valid TaskSaveRequest request, HttpServletRequest httpServletRequest) { + public ResponseEntity createTask( + @RequestBody @Validated(CreateGroup.class) @Valid TaskSaveRequest request, + HttpServletRequest httpServletRequest) { TaskResponse response = taskService.createTask(request, httpServletRequest); - return ResponseEntity.ok( - CommonResponse.create(true, "업무 생성 성공", response, - OffsetDateTime.now())); + return ResponseEntity.ok(ApiResponseDto.success("업무 생성에 성공하였습니다.", response)); } @GetMapping("/{id}") - public ResponseEntity> findTask(@PathVariable @NotNull Long id) { + public ResponseEntity findTask(@PathVariable @NotNull Long id) { TaskResponse response = taskService.findTask(id); - return ResponseEntity.ok( - CommonResponse.create(true, "업무 상세조회 성공", response, - OffsetDateTime.now())); + return ResponseEntity.ok(ApiResponseDto.success("업무 상세조회에 성공하였습니다.", response)); } @GetMapping - public ResponseEntity>> findTasks( + public ResponseEntity findTasks( @RequestParam(defaultValue = "1") @Min(1) int page, @RequestParam(defaultValue = "5") @Min(5) int size, @RequestParam(defaultValue = "") String search, @@ -69,28 +66,23 @@ public ResponseEntity>> findTasks( Page response = taskService.findTasks(pageable, search, status); - return ResponseEntity.ok( - CommonResponse.create(true, "업무 리스트 조회 성공", response, - OffsetDateTime.now())); + return ResponseEntity.ok(ApiResponseDto.success("업무 리스트 조회에 성공하였습니다.", response)); } @DeleteMapping("/{id}") - public ResponseEntity> deleteTask(@PathVariable @NotNull Long id) { + public ResponseEntity deleteTask(@PathVariable @NotNull Long id) { taskService.deleteTask(id); - return ResponseEntity.ok( - CommonResponse.create(true, "업무 삭제 성공", null, - OffsetDateTime.now())); + return ResponseEntity.ok(ApiResponseDto.success("업무 삭제에 성공하였습니다.", null)); } @PutMapping("/{id}") - public ResponseEntity> updateTask(@PathVariable @NotNull Long id, - @RequestBody @Valid TaskUpdateRequest request) { + public ResponseEntity updateTask(@PathVariable @NotNull Long id, + @RequestBody @Validated(UpdateGroup.class) @Valid TaskSaveRequest request) { TaskResponse response = taskService.updateTask(id, request); - return ResponseEntity.ok( - CommonResponse.create(true, "업무 수정 성공", response, OffsetDateTime.now())); + return ResponseEntity.ok(ApiResponseDto.success("업무 수정에 성공하였습니다.", response)); } } diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java index fc7fd43..01e13b2 100644 --- a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java +++ b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java @@ -1,18 +1,22 @@ package com.example.onederful.domain.task.dto.request; +import com.example.onederful.domain.task.common.UpdateGroup; import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; import jakarta.validation.constraints.FutureOrPresent; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; import java.time.OffsetDateTime; -import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; @Getter -@AllArgsConstructor +@Builder public class TaskSaveRequest { @NotBlank(message = "업무 제목은 필수 항목입니다.") + @Size(min = 1, max = 100, message = "1자 이상 100자 이하로 입력해주세요.") private String title; @NotBlank(message = "업무 내용은 필수 항목입니다.") @@ -24,6 +28,9 @@ public class TaskSaveRequest { @NotNull(message = "관리자 선택은 필수 항목입니다.") private Long assigneeId; + @NotNull(groups = {UpdateGroup.class}, message = "업무의 상태는 필수 항목입니다.") + private ProcessStatus status; + @NotNull(message = "마감일은 필수 항목입니다.") @FutureOrPresent(message = "마감일은 오늘이후만 가능합니다.") private OffsetDateTime dueDate; diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java deleted file mode 100644 index 9633896..0000000 --- a/src/main/java/com/example/onederful/domain/task/dto/request/TaskUpdateRequest.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.example.onederful.domain.task.dto.request; - -import com.example.onederful.domain.task.enums.Priority; -import com.example.onederful.domain.task.enums.ProcessStatus; -import jakarta.validation.constraints.FutureOrPresent; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import java.time.OffsetDateTime; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor -public class TaskUpdateRequest { - - @NotBlank(message = "업무 제목은 필수 항목입니다.") - private String title; - - @NotBlank(message = "업무 내용은 필수 항목입니다.") - private String description; - - @NotNull(message = "업무의 우선순위는 필수 항목입니다.") - private Priority priority; - - @NotNull(message = "관리자 선택은 필수 항목입니다.") - private Long assigneeId; - - @NotNull(message = "업무의 상태는 필수 항목입니다.") - private ProcessStatus status; - - @NotNull(message = "마감일은 필수 항목입니다.") - @FutureOrPresent(message = "마감일은 오늘이후만 가능합니다.") - private OffsetDateTime dueDate; -} From 0aedd5b6a9b4c85dea67e7ddccef87173e25cc94 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 15:26:55 +0900 Subject: [PATCH 077/123] =?UTF-8?q?feature=20:=20=EC=98=88=EC=99=B8?= =?UTF-8?q?=EC=B2=98=EB=A6=AC=20/=20Aop=20=EC=82=AC=EC=9A=A9=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20=EA=B3=B5=ED=86=B5=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?Aop=20=EB=A1=9C=EA=B7=B8=20=EB=8B=B4=EB=8B=B9=ED=8C=80=EC=9B=90?= =?UTF-8?q?=EC=9D=98=20=EC=9A=94=EC=B2=AD=EC=9C=BC=EB=A1=9C=20id=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=B3=B8=20=EB=A9=94=EC=84=9C?= =?UTF-8?q?=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/task/service/TaskService.java | 40 +++++++++++-------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index dde64f6..816b001 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -1,22 +1,21 @@ package com.example.onederful.domain.task.service; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; -import com.example.onederful.domain.task.dto.request.TaskUpdateRequest; import com.example.onederful.domain.task.dto.response.TaskResponse; import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.repository.TaskRepository; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.exception.CustomException; +import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; -import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.web.server.ResponseStatusException; @Service @RequiredArgsConstructor @@ -31,8 +30,10 @@ public TaskResponse createTask(TaskSaveRequest request, HttpServletRequest httpS Long userId = jwtUtil.extractId(httpServletRequest); - User me = userRepository.findById(userId).orElseThrow(); - User manager = userRepository.findById(request.getAssigneeId()).orElseThrow(); + User me = userRepository.findById(userId) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); + User manager = userRepository.findById(request.getAssigneeId()) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); Task task = Task.builder() .title(request.getTitle()) @@ -52,7 +53,8 @@ public TaskResponse createTask(TaskSaveRequest request, HttpServletRequest httpS @Transactional(readOnly = true) public TaskResponse findTask(Long id) { - Task task = taskRepository.findById(id).orElseThrow(); + Task task = taskRepository.findById(id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); return TaskResponse.of(task); } @@ -68,36 +70,36 @@ public Page findTasks(Pageable pageable, String search, ProcessSta @Transactional public void deleteTask(Long id) { - Task task = taskRepository.findById(id).orElseThrow(); + Task task = taskRepository.findById(id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); task.delete(); } @Transactional - public TaskResponse updateTask(Long id, TaskUpdateRequest request) { + public TaskResponse updateTask(Long id, TaskSaveRequest request) { - Task task = taskRepository.findById(id).orElseThrow(); - User assignee = userRepository.findById(request.getAssigneeId()).orElseThrow(); + Task task = taskRepository.findById(id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + User assignee = userRepository.findById(request.getAssigneeId()) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); if (task.getStatus() == ProcessStatus.DONE) { if (request.getStatus() != ProcessStatus.DONE) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "DONE 상태는 이전 상태로 변경 할 수 없습니다."); + throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } } if (task.getStatus() == ProcessStatus.TODO) { if (request.getStatus() != ProcessStatus.IN_PROGRESS) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "TODO -> IN_PROCESS으로만 상태 변경이 가능합니다."); + throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } task.taskStart(); } if (task.getStatus() == ProcessStatus.IN_PROGRESS) { if (request.getStatus() != ProcessStatus.DONE) { - throw new ResponseStatusException(HttpStatus.BAD_REQUEST, - "IN_PROCESS -> DONE으로만 상태 변경이 가능합니다."); + throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } } @@ -107,4 +109,10 @@ public TaskResponse updateTask(Long id, TaskUpdateRequest request) { return TaskResponse.of(task); } + + @Transactional(readOnly = true) + public Task findById(Long id) { + return taskRepository.findById(id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + } } From 297a56039dc96a0034175119ae7f26bfc903d54c Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 15:27:20 +0900 Subject: [PATCH 078/123] =?UTF-8?q?feat=20:=20=EC=97=85=EB=AC=B4=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20Enum=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/exception/ErrorCode.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index e263aac..afb8069 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -7,11 +7,16 @@ @AllArgsConstructor @Getter public enum ErrorCode { - DUPLICATE_USER(HttpStatus.CONFLICT,"이미 존재하는 사용자입니다."), - BAD_REQUEST(HttpStatus.BAD_REQUEST,"잘못된 사용자명 또는 비밀번호입니다."), - UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"인증이 필요합니다."), - INVALID_PASSWORD(HttpStatus.UNAUTHORIZED,"비밀번호가 일치하지 않습니다."), - LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."); + DUPLICATE_USER(HttpStatus.CONFLICT, "이미 존재하는 사용자입니다."), + BAD_REQUEST(HttpStatus.BAD_REQUEST, "잘못된 사용자명 또는 비밀번호입니다."), + UNAUTHORIZED(HttpStatus.UNAUTHORIZED, "인증이 필요합니다."), + INVALID_PASSWORD(HttpStatus.UNAUTHORIZED, "비밀번호가 일치하지 않습니다."), + LOGOUT_FAIL(HttpStatus.UNAUTHORIZED, "로그아웃에 실패하였습니다."), + NONEXISTENT_USER(HttpStatus.BAD_REQUEST, "존재하지 않는 사용자입니다."), + + // Task Error + NONEXISTENT_TASK(HttpStatus.BAD_REQUEST, "존재하지 않는 테스크입니다."), + BAD_REQUEST_STATUS(HttpStatus.BAD_REQUEST, "업무 상태변경은 바로 다음 단계로만 가능합니다."); private final HttpStatus status; private final String message; From cb4a0492d5ce4a9fd9d7f6e9c44edea224789249 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 15:28:05 +0900 Subject: [PATCH 079/123] =?UTF-8?q?refactor=20:=20TaskSaveRequest=20?= =?UTF-8?q?=EA=B7=B8=EB=A3=B9=ED=99=94=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EC=83=9D=EC=84=B1=EC=9E=90=20=EB=B0=A9?= =?UTF-8?q?=EC=8B=9D=20->=20Builder=20=ED=8C=A8=ED=84=B4=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=EC=9C=BC=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/task/service/TaskServiceTest.java | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java index b8a1d3c..82a6092 100644 --- a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java +++ b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java @@ -6,7 +6,6 @@ import static org.mockito.Mockito.verify; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; -import com.example.onederful.domain.task.dto.request.TaskUpdateRequest; import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.Priority; import com.example.onederful.domain.task.enums.ProcessStatus; @@ -53,8 +52,14 @@ public class TaskServiceTest { @DisplayName("업무 생성이 성공한다.") void 업무_생성_성공_테스트() { //given - TaskSaveRequest request = new TaskSaveRequest("title", "description", Priority.LOW, - 1L, OffsetDateTime.parse("2027-04-02T23:59:59Z")); + TaskSaveRequest request = TaskSaveRequest.builder() + .title("title") + .description("description") + .priority(Priority.LOW) + .assigneeId(1L) + .dueDate(OffsetDateTime.parse("2027-04-02T23:59:59Z")) + .build(); + HttpServletRequest httpServletRequest = new MockHttpServletRequest(); Long userId = 1L; @@ -286,8 +291,14 @@ public class TaskServiceTest { Long id = 1L; - TaskUpdateRequest request = new TaskUpdateRequest("title", "description", Priority.MEDIUM, - 2L, ProcessStatus.IN_PROGRESS, OffsetDateTime.parse("2027-04-02T23:59:59Z")); + TaskSaveRequest request = TaskSaveRequest.builder() + .title("title") + .description("description") + .priority(Priority.LOW) + .assigneeId(1L) + .status(ProcessStatus.IN_PROGRESS) + .dueDate(OffsetDateTime.parse("2027-04-02T23:59:59Z")) + .build(); Long userId = 1L; From b1e4f33d240549c691fda161df71f0924d7cb4fe Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 15:36:58 +0900 Subject: [PATCH 080/123] =?UTF-8?q?fix:=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20?= =?UTF-8?q?=EA=B2=80=EC=82=AC=20=EC=B6=94=EA=B0=80,=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=EB=84=A4=EC=9D=B4=EC=85=98=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80,=20CommentRequestDto=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 34 +++++++++++++------ .../domain/comment/dto/CommentRequestDto.java | 17 ++++++++++ .../comment/dto/CreateCommentRequestDto.java | 14 -------- .../dto/FindCommentByContentRequestDto.java | 14 -------- .../comment/dto/UpdateCommentRequestDto.java | 13 ------- .../comment/repository/CommentRepository.java | 3 ++ .../comment/service/CommentService.java | 9 +++++ 7 files changed, 53 insertions(+), 51 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/CommentRequestDto.java delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 89240cc..ec65e8b 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -4,7 +4,10 @@ import com.example.onederful.domain.comment.service.CommentService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.springframework.http.HttpStatus; +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.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -19,19 +22,17 @@ public class CommentController { // 댓글 생성 @PostMapping("/tasks/{task_id}/comments") - public ResponseEntity> save (@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CreateCommentRequestDto requestDto){ + public ResponseEntity> save(@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CommentRequestDto requestDto) { CreateCommentResponseDataDto createCommentResponseDataDto = - commentService.save(task_id,httpServletRequest, requestDto.getContent()); - ResponseDto responseDto = ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto); - - return ResponseEntity.ok(responseDto); + commentService.save(task_id, httpServletRequest, requestDto.getContent()); + return ResponseEntity.ok(ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto)); } // 댓글 수정 @PatchMapping("/tasks/{task_id}/comments/{comment_id}") public ResponseEntity> updateComment( - @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody UpdateCommentRequestDto requestDto, HttpServletRequest httpServletRequest + @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody CommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { UpdateCommentResponseDataDto updateCommentResponseDataDto = commentService.updateComment(task_id, comment_id, requestDto.getContent(), httpServletRequest); @@ -46,17 +47,30 @@ public ResponseEntity>> findAllCommentB return ResponseEntity.ok(ResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDataDtoList)); } + // 테스크별 댓글 조회 페이지화 + @GetMapping("/tasks/{task_id}/comments/pages") + public ResponseEntity>> findAllCommentByTaskIdInPage( + @PathVariable Long task_id, + @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "10") int size + ) { + Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt")); + + Page commentResponseDtoInPage = commentService.findAllCommentByTaskIdInPage(task_id,pageable); + return ResponseEntity.ok(ResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDtoInPage)); + } + // 내용으로 댓글 조회 @GetMapping("/search") - public ResponseEntity>> findCommentByContent(@RequestBody FindCommentByContentRequestDto requestDto){ + public ResponseEntity>> findCommentByContent(@RequestBody CommentRequestDto requestDto) { List commentResponseDataDtoList = commentService.findCommentByContent(requestDto.getContent()); - return ResponseEntity.ok(ResponseDto.success( requestDto.getContent() + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); + return ResponseEntity.ok(ResponseDto.success(requestDto.getContent() + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); } // 댓글 삭제 @DeleteMapping("/tasks/{task_id}/comments/{comment_id}") - public ResponseEntity> deleteComment(@PathVariable Long task_id, @PathVariable Long comment_id){ + public ResponseEntity> deleteComment(@PathVariable Long task_id, @PathVariable Long comment_id) { commentService.deleteComment(comment_id); return ResponseEntity.ok(ResponseDto.success("댓글이 삭제되었습니다.", null)); } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentRequestDto.java new file mode 100644 index 0000000..d6c91aa --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentRequestDto.java @@ -0,0 +1,17 @@ +package com.example.onederful.domain.comment.dto; + +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Getter; + +@Getter +public class CommentRequestDto { + + @Size(min=1, max = 500, message = "댓글 내용은 1~500자로 입력해주세요.") + @NotNull(message = "댓글 내용은 필수 항목입니다.") + private final String content; + + public CommentRequestDto(String content){ + this.content = content; + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java deleted file mode 100644 index 1095315..0000000 --- a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentRequestDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.onederful.domain.comment.dto; - -import lombok.Getter; - -@Getter -public class CreateCommentRequestDto { - - private final String content; - - public CreateCommentRequestDto(String writer, String content) { - this.content = content; - } - -} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java deleted file mode 100644 index 59833b3..0000000 --- a/src/main/java/com/example/onederful/domain/comment/dto/FindCommentByContentRequestDto.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.onederful.domain.comment.dto; - -import lombok.Getter; - -@Getter -public class FindCommentByContentRequestDto { - - private final String content; - - - public FindCommentByContentRequestDto(String content) { - this.content = content; - } -} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java deleted file mode 100644 index c3950ea..0000000 --- a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentRequestDto.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.example.onederful.domain.comment.dto; - -import lombok.Getter; - -@Getter -public class UpdateCommentRequestDto { - - private final String content; - - public UpdateCommentRequestDto(String content){ - this.content = content; - } -} diff --git a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java index 6acb12d..d770be1 100644 --- a/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java +++ b/src/main/java/com/example/onederful/domain/comment/repository/CommentRepository.java @@ -1,6 +1,8 @@ package com.example.onederful.domain.comment.repository; import com.example.onederful.domain.comment.entity.Comment; +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.data.repository.query.Param; @@ -10,6 +12,7 @@ public interface CommentRepository extends JpaRepository { List findAllByTaskIdOrderByCreatedAtDesc(Long taskId); + Page findByTaskIdAndIsDeletedFalse(Long task_id, Pageable pageable); @Query("SELECT c from Comment c WHERE(c.content LIKE %:keyword% OR c.user.username LIKE %:keyword%) AND c.isDeleted = false") List findByContentOrUsername(@Param("keyword") String keyword); diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 6484d96..d28c7c8 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -15,6 +15,8 @@ import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -82,6 +84,13 @@ public List findAllCommentByTaskId(Long task_id){ .collect(Collectors.toList()); } + public Page findAllCommentByTaskIdInPage(Long task_id, Pageable pageable){ + // 페이징 대상 조회 + final Page commentListByIdInPage = commentRepository.findByTaskIdAndIsDeletedFalse(task_id, pageable); + + return commentListByIdInPage.map(CommentResponseDataDto::from); + } + public List findCommentByContent(String content){ From 7a22f02c7a0405e8b14514df0c65be5d6973bcb9 Mon Sep 17 00:00:00 2001 From: saevit Date: Wed, 18 Jun 2025 15:57:09 +0900 Subject: [PATCH 081/123] =?UTF-8?q?feat:=20task=20=EC=83=81=ED=83=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20=EA=B8=B0=EB=A1=9D=EB=90=98=EB=A1=9D=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/HttpRequestUtil.java | 2 +- .../onederful/domain/log/LoggingAspect.java | 84 +++++++++++++------ .../domain/log/service/LogService.java | 35 ++++---- 3 files changed, 82 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java index e662029..f4ce47a 100644 --- a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java +++ b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java @@ -18,7 +18,7 @@ public class HttpRequestUtil { private final JwtUtil jwtUtil; - // HttpServletRequest으로부터 요청 ip, 메서드, url, userId + // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userId public RequestInfo getRequestInfo() { ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attrs == null) { diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index f27541c..e050e6f 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -1,11 +1,20 @@ package com.example.onederful.domain.log; +import java.util.Objects; + +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; +import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; +import com.example.onederful.domain.log.enums.Activity; import com.example.onederful.domain.log.service.LogService; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.task.service.TaskService; import lombok.RequiredArgsConstructor; @@ -15,8 +24,12 @@ public class LoggingAspect { private final HttpRequestUtil httpRequestUtil; + private final TaskService taskService; private final LogService logService; + @Pointcut("execution(* com.example..UserService.login(..))") + public void loginMethod() {} + @Pointcut( "execution(* com.example..TaskService.createTask(..)) || " + "execution(* com.example..TaskService.updateTask(..)) || " + @@ -24,8 +37,19 @@ public class LoggingAspect { ) public void cudMethods() {} - @Pointcut("execution(* com.example..UserService.login(..))") - public void loginMethod() {} + @Pointcut("execution(* com.example..TaskService.updateTask(..))") + public void updateTaskMethod() {} + + // 로그인 + @AfterReturning(pointcut = "loginMethod()", returning = "result") + public void logLoginMethod(Object result) { + + // HttpServletRequest으로부터 요청 ip, 메서드, url + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + + // 로그 저장 + logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); + } // 생성, 수정, 삭제 @AfterReturning(pointcut = "cudMethods()", returning = "result") @@ -39,29 +63,41 @@ public void logCudMethods(Object result) { } // 상태 변경 - // @Around("serviceMethods()") - // public void logTaskStatusChange() { - // // 변경 전 task 상태 조회 - // taskService.findStatus(); - // - // // 메서드 실행 - // - // // 변경 후 tast 상태 조회 및 다른 정보들 뽑기 - // taskService.findStatus(); - // - // // 로그 저장 - // logService.saveLog(); - // } - - // 로그인/로그아웃 - @AfterReturning(pointcut = "loginMethod()", returning = "result") - public void logLoginMethod(Object result) { - System.out.println("메서드 정상 실행 후: 로그 기록"); + @Around("updateTaskMethod()") + public Object logTaskStatusChange(ProceedingJoinPoint joinPoint) throws Throwable { + Object[] args = joinPoint.getArgs(); + Long taskId = (Long) args[0]; // 첫 번째 인자가 taskId - // HttpServletRequest으로부터 요청 ip, 메서드, url - HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + // 기존 task 상태 조회 + Task beforeTask = taskService.findById(taskId); // 서비스 계층 사용 + ProcessStatus beforeStatus = beforeTask != null ? beforeTask.getStatus() : null; - // 로그 저장 - logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); + // 메서드 실행 + Object result = joinPoint.proceed(); + + // 변경 후 task 상태 조회 + Task afterTask = taskService.findById(taskId); + ProcessStatus afterStatus = afterTask != null ? afterTask.getStatus() : null; + + // 변경되었는지 비교 후 로그 기록 + Activity activity = null; + if (Objects.equals(beforeStatus, ProcessStatus.TODO) && Objects.equals(afterStatus, ProcessStatus.IN_PROGRESS)) + { + activity = Activity.TASK_STATUS_TODO_TO_IN_PROGRESS; + } + else if (Objects.equals(beforeStatus, ProcessStatus.IN_PROGRESS) && Objects.equals(afterStatus, ProcessStatus.DONE)) + { + activity = Activity.TASK_STATUS_IN_PROGRESS_TO_DONE; + } + + if(activity != null) { + // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userid + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + + // 로그 저장 + logService.saveTaskStatusChangeLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), taskId, activity); + } + + return result; } } diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index f9d3e51..aee3a9c 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -14,7 +14,6 @@ import com.example.onederful.domain.log.repository.LogRepository; import com.example.onederful.domain.log.repository.LogSpecification; import com.example.onederful.domain.task.dto.response.TaskResponse; -import com.example.onederful.domain.user.dto.ApiResponseDto; import com.example.onederful.domain.user.dto.Tokeninfo; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; @@ -68,8 +67,6 @@ else if (method.equals(Method.DELETE) && url.contains("/tasks")) { activity = Activity.TASK_DELETED; } - // if (activity == null) 예외 처리 - // 대상 id -> 생성인 경우 응답에서 / 수정과 삭제의 경우 url 마지막에서 찾기 Long targetId = null; if (activity.equals(Activity.TASK_CREATED)) { @@ -83,8 +80,6 @@ else if (method.equals(Method.DELETE) && url.contains("/tasks")) { targetId = Long.parseLong(lastPart); } - // if (targetId == null) 예외 처리 - // 로그 DB에 저장 Log log = Log.builder() .user(user) @@ -102,12 +97,9 @@ else if (method.equals(Method.DELETE) && url.contains("/tasks")) { public void saveLoginLog(String ip, Method method, String url, Object result) { // userId Long userId = null; - if (result instanceof ApiResponseDto) { - Object data = ((ApiResponseDto) result).getData(); - if (data instanceof Tokeninfo) { - String token = ((Tokeninfo) data).getToken(); - userId = jwtUtil.extractAllClaims(token).get("id", Long.class); - } + if (result instanceof Tokeninfo) { + String token = ((Tokeninfo) result).getToken(); + userId = jwtUtil.extractAllClaims(token).get("id", Long.class); } // 현재 유저 조회 @@ -118,12 +110,27 @@ public void saveLoginLog(String ip, Method method, String url, Object result) { // 활동 유형 Activity activity = Activity.USER_LOGGED_IN; - // if (activity == null) 예외 처리 - // 대상 id Long targetId = userId; - // if (targetId == null) 예외 처리 + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } + + public void saveTaskStatusChangeLog(String ip, Method method, String url, Long userId, Long targetId, Activity activity) { + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); // 로그 DB에 저장 Log log = Log.builder() From 143f3c507e1c5b1519820f6b3ea0cfd512ba9ff9 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 16:10:26 +0900 Subject: [PATCH 082/123] =?UTF-8?q?feat=20:=20CORS=20=EC=84=A4=EC=A0=95=20?= =?UTF-8?q?,=20=ED=95=84=ED=84=B0=20=EB=93=B1=EB=A1=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/config/WebConfig.java | 46 ++++++++++++++++++- .../example/onederful/filter/JwtFilter.java | 6 ++- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/onederful/config/WebConfig.java b/src/main/java/com/example/onederful/config/WebConfig.java index 90fc4fa..bb8ddf8 100644 --- a/src/main/java/com/example/onederful/config/WebConfig.java +++ b/src/main/java/com/example/onederful/config/WebConfig.java @@ -5,9 +5,51 @@ import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +import java.util.List; @Configuration -public class WebConfig { +public class WebConfig implements WebMvcConfigurer { + + @Bean + public FilterRegistrationBean corsFilter(){ + + CorsConfiguration config = new CorsConfiguration(); + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + + // 도메인 설정 + config.setAllowedOriginPatterns(List.of( + "http://localhost:3100" + )); + + // HTTP 메서드 설정 + config.setAllowedMethods(List.of("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")); + + // 헤더 설정 + config.setAllowedHeaders(List.of("*")); + + // 응답 헤더 + config.setExposedHeaders(List.of( + "Authorization", + "Content-Type" + )); + + // 인증 정보 허용 + config.setAllowCredentials(true); + + // 모든 경로에 설정 적용 + source.registerCorsConfiguration("/**", config); + + FilterRegistrationBean bean = new FilterRegistrationBean<>(new CorsFilter(source)); + + bean.setOrder(0); + + return bean; + } @Bean public FilterRegistrationBean jwtFilter(JwtUtil jwtUtil){ @@ -19,4 +61,6 @@ public FilterRegistrationBean jwtFilter(JwtUtil jwtUtil){ return registrationBean; } + + } diff --git a/src/main/java/com/example/onederful/filter/JwtFilter.java b/src/main/java/com/example/onederful/filter/JwtFilter.java index 99c30fb..df25a03 100644 --- a/src/main/java/com/example/onederful/filter/JwtFilter.java +++ b/src/main/java/com/example/onederful/filter/JwtFilter.java @@ -28,6 +28,10 @@ public void doFilter( String authorizationHeader = request.getHeader("Authorization"); + if("OPTIONS".equals(request.getMethod())) { + filterChain.doFilter(servletRequest, servletResponse); + } + // 회원가입, 로그인 경우 if (requestURI.startsWith("/api/auth/register") || requestURI.startsWith("/api/auth/login") || @@ -48,7 +52,7 @@ public void doFilter( // "Bearer" 빼고 확인 String jwt = authorizationHeader.substring(7); -// // 토큰 검증 + // 토큰 검증 String errorMessage = jwtUtil.validateToken(jwt); if (errorMessage != null) { errorResponse(response, HttpServletResponse.SC_FORBIDDEN, errorMessage); From 144ccbf3e580c2037adda973d318fdae66f3ed80 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 16:19:19 +0900 Subject: [PATCH 083/123] =?UTF-8?q?feat=20:=20Task=20=EC=83=81=ED=83=9C?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=EB=A1=9C=20=EC=9D=B8=ED=95=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/controller/TaskController.java | 21 +++-- .../dto/request/TaskStatusUpdateRequest.java | 14 ++++ .../onederful/domain/task/entity/Task.java | 4 + .../domain/task/service/TaskServiceTest.java | 83 +++++++++++++++++++ 4 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/task/dto/request/TaskStatusUpdateRequest.java diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java index b3d402f..6b9562f 100644 --- a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -4,7 +4,9 @@ import com.example.onederful.domain.task.common.CreateGroup; import com.example.onederful.domain.task.common.UpdateGroup; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.request.TaskStatusUpdateRequest; import com.example.onederful.domain.task.dto.response.TaskResponse; +import com.example.onederful.domain.task.dto.response.TasksResponse; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.service.TaskService; import jakarta.servlet.http.HttpServletRequest; @@ -12,7 +14,6 @@ import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; 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.Direction; @@ -20,6 +21,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PatchMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -56,15 +58,14 @@ public ResponseEntity findTask(@PathVariable @NotNull Long id) { @GetMapping public ResponseEntity findTasks( - @RequestParam(defaultValue = "1") @Min(1) int page, + @RequestParam(defaultValue = "0") @Min(0) int page, @RequestParam(defaultValue = "5") @Min(5) int size, @RequestParam(defaultValue = "") String search, @RequestParam(defaultValue = "TODO") ProcessStatus status ) { - Pageable pageable = PageRequest.of(page - 1, size, Direction.ASC, "dueDate"); + Pageable pageable = PageRequest.of(page, size, Direction.ASC, "dueDate"); - Page response = taskService.findTasks(pageable, search, - status); + TasksResponse response = taskService.findTasks(pageable, search, status); return ResponseEntity.ok(ApiResponseDto.success("업무 리스트 조회에 성공하였습니다.", response)); } @@ -85,4 +86,14 @@ public ResponseEntity updateTask(@PathVariable @NotNull Long id, return ResponseEntity.ok(ApiResponseDto.success("업무 수정에 성공하였습니다.", response)); } + + @PatchMapping("/{id}/status") + public ResponseEntity updateTaskStatus(@PathVariable @NotNull Long id, + @RequestBody @Valid + TaskStatusUpdateRequest request) { + + TaskResponse response = taskService.updateTaskStatus(id, request); + + return ResponseEntity.ok(ApiResponseDto.success("업무 상태 변경에 성공하였습니다.", response)); + } } diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskStatusUpdateRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskStatusUpdateRequest.java new file mode 100644 index 0000000..4668624 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/request/TaskStatusUpdateRequest.java @@ -0,0 +1,14 @@ +package com.example.onederful.domain.task.dto.request; + +import com.example.onederful.domain.task.enums.ProcessStatus; +import lombok.Getter; + +@Getter +public class TaskStatusUpdateRequest { + + private final ProcessStatus status; + + public TaskStatusUpdateRequest(ProcessStatus status) { + this.status = status; + } +} diff --git a/src/main/java/com/example/onederful/domain/task/entity/Task.java b/src/main/java/com/example/onederful/domain/task/entity/Task.java index f8efa3e..e4d51e8 100644 --- a/src/main/java/com/example/onederful/domain/task/entity/Task.java +++ b/src/main/java/com/example/onederful/domain/task/entity/Task.java @@ -94,6 +94,10 @@ public void updateTask(String title, String content, Priority priority, User ass this.status = status; } + public void updateTaskStatus(ProcessStatus status) { + this.status = status; + } + public void delete() { this.isDeleted = true; this.deletedAt = LocalDateTime.now(); diff --git a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java index 82a6092..7a822aa 100644 --- a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java +++ b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java @@ -6,6 +6,7 @@ import static org.mockito.Mockito.verify; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.request.TaskStatusUpdateRequest; import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.Priority; import com.example.onederful.domain.task.enums.ProcessStatus; @@ -346,4 +347,86 @@ public class TaskServiceTest { Assertions.assertEquals(task.getAssignee(), manager); Assertions.assertEquals(ProcessStatus.IN_PROGRESS, task.getStatus()); } + + @Test + @DisplayName("업무 상태 변경이 성공한다.") + void 업무_상태_변경_성공_테스트() { + //given + + Long id = 1L; + + TaskStatusUpdateRequest request = new TaskStatusUpdateRequest(ProcessStatus.IN_PROGRESS); + + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + Task task = Task.builder() + .id(2L) + .title("test") + .description("description") + .priority(Priority.LOW) + .assignee(me) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task, "updatedAt", LocalDateTime.now()); + + given(taskRepository.findById(anyLong())).willReturn(Optional.of(task)); + + //when + + taskService.updateTaskStatus(id, request); + + //then + + Assertions.assertEquals(ProcessStatus.IN_PROGRESS, task.getStatus()); + } + + @Test + @DisplayName("기본 조회가 성공한다.") + void 기본_조회_성공_테스트() { + Long id = 1L; + + Long userId = 1L; + + User me = User.builder() + .id(userId) + .email("me@example.com") + .name("me1") + .password("!@A12345") + .role(Role.USER) + .username("me1") + .build(); + + Task task = Task.builder() + .id(2L) + .title("test") + .description("description") + .priority(Priority.LOW) + .assignee(me) + .user(me) + .status(ProcessStatus.TODO) + .dueDate(LocalDateTime.now()) + .build(); + + ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); + ReflectionTestUtils.setField(task, "updatedAt", LocalDateTime.now()); + + given(taskRepository.findById(anyLong())).willReturn(Optional.of(task)); + + taskService.findById(id); + + verify(taskRepository).findById(anyLong()); + } } From 039a507f2e17748a6db1155e3a6dbdfb1b3ff113 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Wed, 18 Jun 2025 16:20:33 +0900 Subject: [PATCH 084/123] =?UTF-8?q?feat=20:=20Pagination=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20DTO=20=EC=83=9D=EC=84=B1=20=EA=B8=B0=EC=A1=B4=20Pag?= =?UTF-8?q?e=20=ED=83=80=EC=9E=85=EC=97=90=EC=84=9C=20=EA=B0=9C=EB=B3=84?= =?UTF-8?q?=20DTO=EB=A1=9C=20=EC=9D=91=EB=8B=B5=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/dto/response/TasksResponse.java | 16 +++++ .../domain/task/service/TaskService.java | 59 +++++++++++++------ 2 files changed, 58 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java b/src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java new file mode 100644 index 0000000..7a2f6dc --- /dev/null +++ b/src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java @@ -0,0 +1,16 @@ +package com.example.onederful.domain.task.dto.response; + +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class TasksResponse { + + private List content; + private Long totalElements; + private Long totalPages; + private Long size; + private Long number; +} diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index 816b001..0d8b239 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -1,7 +1,9 @@ package com.example.onederful.domain.task.service; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; +import com.example.onederful.domain.task.dto.request.TaskStatusUpdateRequest; import com.example.onederful.domain.task.dto.response.TaskResponse; +import com.example.onederful.domain.task.dto.response.TasksResponse; import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.repository.TaskRepository; @@ -11,6 +13,7 @@ import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; @@ -60,11 +63,17 @@ public TaskResponse findTask(Long id) { } @Transactional(readOnly = true) - public Page findTasks(Pageable pageable, String search, ProcessStatus status) { + public TasksResponse findTasks(Pageable pageable, String search, ProcessStatus status) { Page tasks = taskRepository.findTasks(search, status, pageable); - return tasks.map(TaskResponse::of); + return TasksResponse.builder() + .content(tasks.getContent().stream().map(TaskResponse::of).collect(Collectors.toList())) + .totalElements(tasks.getTotalElements()) + .size((long) tasks.getSize()) + .number((long) tasks.getNumber()) + .totalPages((long) tasks.getTotalPages()) + .build(); } @Transactional @@ -76,6 +85,18 @@ public void deleteTask(Long id) { task.delete(); } + @Transactional + public TaskResponse updateTaskStatus(Long id, TaskStatusUpdateRequest request) { + Task task = taskRepository.findById(id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + + taskUpdateValid(task, request.getStatus()); + + task.updateTaskStatus(request.getStatus()); + + return TaskResponse.of(task); + } + @Transactional public TaskResponse updateTask(Long id, TaskSaveRequest request) { @@ -84,35 +105,39 @@ public TaskResponse updateTask(Long id, TaskSaveRequest request) { User assignee = userRepository.findById(request.getAssigneeId()) .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); + taskUpdateValid(task, request.getStatus()); + + task.updateTask(request.getTitle(), request.getDescription(), request.getPriority(), + assignee, + request.getDueDate().toLocalDateTime(), request.getStatus()); + + return TaskResponse.of(task); + } + + @Transactional(readOnly = true) + public Task findById(Long id) { + return taskRepository.findById(id) + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + } + + private void taskUpdateValid(Task task, ProcessStatus status) { if (task.getStatus() == ProcessStatus.DONE) { - if (request.getStatus() != ProcessStatus.DONE) { + if (status != ProcessStatus.DONE) { throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } } if (task.getStatus() == ProcessStatus.TODO) { - if (request.getStatus() != ProcessStatus.IN_PROGRESS) { + if (status != ProcessStatus.IN_PROGRESS) { throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } task.taskStart(); } if (task.getStatus() == ProcessStatus.IN_PROGRESS) { - if (request.getStatus() != ProcessStatus.DONE) { + if (status != ProcessStatus.DONE) { throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } } - - task.updateTask(request.getTitle(), request.getDescription(), request.getPriority(), - assignee, - request.getDueDate().toLocalDateTime(), request.getStatus()); - - return TaskResponse.of(task); - } - - @Transactional(readOnly = true) - public Task findById(Long id) { - return taskRepository.findById(id) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); } } From cf3ff7900a755d903e7cfd3bee33ad3ed3b224aa Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 16:27:29 +0900 Subject: [PATCH 085/123] =?UTF-8?q?fix:=20=ED=8E=98=EC=9D=B4=EC=A7=80?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EC=85=98=20=EC=8B=9C=EC=9E=91=200=EC=9C=BC?= =?UTF-8?q?=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/comment/controller/CommentController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index ec65e8b..1c3c94c 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -51,10 +51,10 @@ public ResponseEntity>> findAllCommentB @GetMapping("/tasks/{task_id}/comments/pages") public ResponseEntity>> findAllCommentByTaskIdInPage( @PathVariable Long task_id, - @RequestParam(defaultValue = "1") int page, + @RequestParam(defaultValue = "0") int page, @RequestParam(defaultValue = "10") int size ) { - Pageable pageable = PageRequest.of(page - 1, size, Sort.by(Sort.Direction.DESC, "createdAt")); + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page commentResponseDtoInPage = commentService.findAllCommentByTaskIdInPage(task_id,pageable); return ResponseEntity.ok(ResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDtoInPage)); From 21f6d83080d64578694b95e16d2ecf97cce82a68 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 16:40:33 +0900 Subject: [PATCH 086/123] =?UTF-8?q?fix:=20ErrorCode=20=EB=AC=B8=EB=B2=95?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0,=20user=20not=20foun?= =?UTF-8?q?d=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C=20=EC=A4=91=EB=B3=B5?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/dashboard/service/DashboardService.java | 2 +- src/main/java/com/example/onederful/exception/ErrorCode.java | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java b/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java index 2bd4d92..cc46aa1 100644 --- a/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java +++ b/src/main/java/com/example/onederful/domain/dashboard/service/DashboardService.java @@ -27,7 +27,7 @@ public StatisticsResponseDto getStatistics(){ public List getMyTasksToday(Long userId){ - userRepository.findById(userId).orElseThrow(() -> new CustomException(ErrorCode.USER_NOT_EXIST)); + userRepository.findById(userId).orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); List tasks = dashboardRepository.getMyTasksToday(userId); List dtos = tasks.stream() diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index a1412e0..e75e841 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -14,9 +14,6 @@ public enum ErrorCode { INVALID_PASSWORD(HttpStatus.UNAUTHORIZED,"비밀번호가 일치하지 않습니다."), LOGOUT_FAIL(HttpStatus.UNAUTHORIZED,"로그아웃에 실패하였습니다."), - - USER_NOT_EXIST(HttpStatus.NOT_FOUND, "존재하지 않는 사용자입니다."); - // Comment NONEXISTENT_USER(HttpStatus.BAD_REQUEST, "존재하지 않는 사용자입니다."), NONEXISTENT_TASK(HttpStatus.BAD_REQUEST, "존재하지 않는 테스크입니다."), From f10deed5f22f59d2f2085755d7f9a5b92ea9ce91 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 16:58:04 +0900 Subject: [PATCH 087/123] =?UTF-8?q?fix:=20=EC=9D=91=EB=8B=B5=EC=8B=9C=20Co?= =?UTF-8?q?mmon=20ApiResponseDto=EB=A1=9C=20=EB=B0=98=ED=99=98=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/DashboardController.java | 10 ++--- .../domain/dashboard/dto/ApiResponse.java | 39 ------------------- 2 files changed, 5 insertions(+), 44 deletions(-) delete mode 100644 src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java diff --git a/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java b/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java index 4a81430..1f1fccb 100644 --- a/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java +++ b/src/main/java/com/example/onederful/domain/dashboard/controller/DashboardController.java @@ -1,6 +1,6 @@ package com.example.onederful.domain.dashboard.controller; -import com.example.onederful.domain.dashboard.dto.ApiResponse; +import com.example.onederful.common.ApiResponseDto; import com.example.onederful.domain.dashboard.dto.MyTasksTodayResponseDto; import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; import com.example.onederful.domain.dashboard.service.DashboardService; @@ -24,11 +24,11 @@ public class DashboardController { private final JwtUtil jwtUtil; @GetMapping("/statistics") - public ResponseEntity> getStatistics(){ + public ResponseEntity getStatistics(){ StatisticsResponseDto data = dashboardService.getStatistics(); return new ResponseEntity<>( - ApiResponse.success( + ApiResponseDto.success( "통계정보를 조회했습니다.", data ), @@ -37,7 +37,7 @@ public ResponseEntity> getStatistics(){ } @GetMapping("/my-tasks-today") - public ResponseEntity>> getMyTasksToday( + public ResponseEntity getMyTasksToday( HttpServletRequest request ){ Long userId = jwtUtil.extractId(request); @@ -45,7 +45,7 @@ public ResponseEntity>> getMyTasksToda List data = dashboardService.getMyTasksToday(userId); return new ResponseEntity<>( - ApiResponse.success( + ApiResponseDto.success( "오늘 내 태스크 정보를 조회했습니다.", data ), diff --git a/src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java b/src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java deleted file mode 100644 index 65adba8..0000000 --- a/src/main/java/com/example/onederful/domain/dashboard/dto/ApiResponse.java +++ /dev/null @@ -1,39 +0,0 @@ -package com.example.onederful.domain.dashboard.dto; - -import com.fasterxml.jackson.annotation.JsonFormat; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.time.LocalDateTime; -import java.time.OffsetDateTime; - -@Getter -@NoArgsConstructor -public class ApiResponse { - - private boolean success;// API 호출 성공/실패 여부 - private String message;// 사용자에게 보여줄 메시지 - private T data;// 실제 데이터 (제네릭 타입) - - // JSON으로 변환될 때 날짜 형식을 지정 - @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'") - private OffsetDateTime timestamp;// 응답 시간 - - // 전체 필드를 초기화하는 생성자 - private ApiResponse(boolean success, String message, T data) { - this.success = success; - this.message = message; - this.data = data; - this.timestamp = OffsetDateTime.now();// 현재 시간으로 자동 설정 - } - - // 성공 응답을 쉽게 만들어주는 static 메서드 - public static ApiResponse success(String message, T data) { - return new ApiResponse<>(true, message, data); - } - - // 실패 응답을 쉽게 만들어주는 static 메서드 - public static ApiResponse error(String message) { - return new ApiResponse<>(false, message, null); - } -} From 4ead2168eb0d4635d5cdd5161e0b03b6b8ecac5c Mon Sep 17 00:00:00 2001 From: kimminsung Date: Wed, 18 Jun 2025 16:58:28 +0900 Subject: [PATCH 088/123] =?UTF-8?q?fix:=20taskDoneRate=20=EC=86=8C?= =?UTF-8?q?=EC=88=98=EC=A0=90=20=EB=91=98=EC=A7=B8=EC=9E=90=EB=A6=AC?= =?UTF-8?q?=EA=B9=8C=EC=A7=80=20=ED=91=9C=EC=8B=9C=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/dashboard/repository/DashboardRepositoryImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java index 4ca0c4e..3e50d22 100644 --- a/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java +++ b/src/main/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryImpl.java @@ -88,7 +88,8 @@ public StatisticsResponseDto getStatistics(){ double taskDoneRate = 0.0; if(total != 0L){ - taskDoneRate = (double) done / total * 100; + taskDoneRate = Math.round((double) done / total * 100 * 100) / 100.0; + } return StatisticsResponseDto.builder() From a48fc4c686db95045bacee1a358a2f39d3a6583e Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 17:13:54 +0900 Subject: [PATCH 089/123] =?UTF-8?q?refactor=20:=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=EC=9D=84=20ApiResponseDto=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 53 +++++++++++++------ 1 file changed, 38 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 1c3c94c..1d43443 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -1,5 +1,6 @@ package com.example.onederful.domain.comment.controller; +import com.example.onederful.common.ApiResponseDto; import com.example.onederful.domain.comment.dto.*; import com.example.onederful.domain.comment.service.CommentService; import jakarta.servlet.http.HttpServletRequest; @@ -8,6 +9,7 @@ import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; @@ -22,57 +24,78 @@ public class CommentController { // 댓글 생성 @PostMapping("/tasks/{task_id}/comments") - public ResponseEntity> save(@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CommentRequestDto requestDto) { + public ResponseEntity save(@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CommentRequestDto requestDto){ CreateCommentResponseDataDto createCommentResponseDataDto = commentService.save(task_id, httpServletRequest, requestDto.getContent()); - return ResponseEntity.ok(ResponseDto.success("댓글이 생성되었습니다.", createCommentResponseDataDto)); + + ApiResponseDto success = ApiResponseDto.success("댓글이 생성되었습니다,", createCommentResponseDataDto); + + return ResponseEntity.status(HttpStatus.OK).body(success); } // 댓글 수정 @PatchMapping("/tasks/{task_id}/comments/{comment_id}") - public ResponseEntity> updateComment( + public ResponseEntity updateComment( @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody CommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { + UpdateCommentResponseDataDto updateCommentResponseDataDto = commentService.updateComment(task_id, comment_id, requestDto.getContent(), httpServletRequest); - return ResponseEntity.ok(ResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto)); + + ApiResponseDto success = ApiResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto); + + return ResponseEntity.status(HttpStatus.OK).body(success); } // 테스크별 댓글 조회 @GetMapping("/tasks/{task_id}/comments") - public ResponseEntity>> findAllCommentByTaskId( + public ResponseEntity findAllCommentByTaskId( @PathVariable Long task_id) { + List commentResponseDataDtoList = commentService.findAllCommentByTaskId(task_id); - return ResponseEntity.ok(ResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDataDtoList)); + + ApiResponseDto success = ApiResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDataDtoList); + + return ResponseEntity.status(HttpStatus.OK).body(success); } // 테스크별 댓글 조회 페이지화 @GetMapping("/tasks/{task_id}/comments/pages") - public ResponseEntity>> findAllCommentByTaskIdInPage( + public ResponseEntity findAllCommentByTaskIdInPage( @PathVariable Long task_id, @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size - ) { - Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); + @RequestParam(defaultValue = "10") int size) { + Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page commentResponseDtoInPage = commentService.findAllCommentByTaskIdInPage(task_id,pageable); - return ResponseEntity.ok(ResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDtoInPage)); + + ApiResponseDto success = ApiResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDtoInPage); + + return ResponseEntity.status(HttpStatus.OK).body(success); } // 내용으로 댓글 조회 @GetMapping("/search") - public ResponseEntity>> findCommentByContent(@RequestBody CommentRequestDto requestDto) { + public ResponseEntity findCommentByContent(@RequestBody CommentRequestDto requestDto) { + List commentResponseDataDtoList = commentService.findCommentByContent(requestDto.getContent()); - return ResponseEntity.ok(ResponseDto.success(requestDto.getContent() + "가 포함된 댓글 목록 ", commentResponseDataDtoList)); + + ApiResponseDto success = ApiResponseDto.success(requestDto.getContent() + "가 포함된 댓글 목록 ", commentResponseDataDtoList); + + return ResponseEntity.status(HttpStatus.OK).body(success); } // 댓글 삭제 @DeleteMapping("/tasks/{task_id}/comments/{comment_id}") - public ResponseEntity> deleteComment(@PathVariable Long task_id, @PathVariable Long comment_id) { + public ResponseEntity deleteComment(@PathVariable Long task_id, @PathVariable Long comment_id) { + commentService.deleteComment(comment_id); - return ResponseEntity.ok(ResponseDto.success("댓글이 삭제되었습니다.", null)); + + ApiResponseDto success = ApiResponseDto.success("댓글이 삭제되었습니다.", null); + + return ResponseEntity.status(HttpStatus.OK).body(success); } } From eedbad840911a97d3df489053abd0402246771a3 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 19:50:20 +0900 Subject: [PATCH 090/123] =?UTF-8?q?refactor=20:=20=EC=83=88=EB=A1=9C?= =?UTF-8?q?=EC=9A=B4=20=EC=97=90=EB=9F=AC=EC=BD=94=EB=93=9C=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/example/onederful/exception/ErrorCode.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index e75e841..f75862c 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -8,7 +8,8 @@ @Getter public enum ErrorCode { // User - DUPLICATE_USER(HttpStatus.CONFLICT,"이미 존재하는 사용자입니다."), + DUPLICATE_USER(HttpStatus.CONFLICT,"이미 존재하는 사용자명입니다."), + DUPLICATE_EMAIL(HttpStatus.CONFLICT,"이미 존재하는 이메일입니다."), BAD_REQUEST(HttpStatus.BAD_REQUEST,"잘못된 사용자명 또는 비밀번호입니다."), UNAUTHORIZED(HttpStatus.UNAUTHORIZED,"인증이 필요합니다."), INVALID_PASSWORD(HttpStatus.UNAUTHORIZED,"비밀번호가 일치하지 않습니다."), From 5ff3840da35547c0b1e197a03d336824941c1c4c Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 19:52:10 +0900 Subject: [PATCH 091/123] =?UTF-8?q?feat=20:=20Bean=20Validation=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=EC=97=90=EC=84=9C?= =?UTF-8?q?=20=EC=98=88=EC=99=B8=20=EA=B1=B8=EB=A6=B4=20=EA=B2=BD=EC=9A=B0?= =?UTF-8?q?=20=ED=95=B8=EB=93=A4=EB=9F=AC=EB=A1=9C=20=EC=BB=A8=ED=8A=B8?= =?UTF-8?q?=EB=A1=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../exception/GlobalExceptionHandler.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java index cfe7bb5..b999e8f 100644 --- a/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java +++ b/src/main/java/com/example/onederful/exception/GlobalExceptionHandler.java @@ -1,9 +1,13 @@ package com.example.onederful.exception; import com.example.onederful.common.ApiResponseDto; +import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.annotation.ControllerAdvice; import org.springframework.web.bind.annotation.ExceptionHandler; +import java.util.Optional; @ControllerAdvice public class GlobalExceptionHandler { @@ -16,4 +20,15 @@ public ResponseEntity handleCustomException(CustomException e){ return ResponseEntity.status(errorCode.getStatus()).body(response); } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleMethodArgumentNotValidException(MethodArgumentNotValidException e){ + String message = Optional.ofNullable(e.getBindingResult().getFieldError()) + .map(FieldError::getDefaultMessage) + .orElse("잘못된 요청입니다."); + + ApiResponseDto response = ApiResponseDto.error(message); + + return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); + } } From 33d73bd570827f86dcea8ea56a4ae86b3209b5d5 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 19:53:45 +0900 Subject: [PATCH 092/123] =?UTF-8?q?refactor=20:=20Bean=20Validation=20?= =?UTF-8?q?=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4=EC=85=98=EC=97=90=20defaul?= =?UTF-8?q?t=20message=20=EC=B6=94=EA=B0=80,=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit refactor : 어노테이션 순서변경(순서에 맞춰서 예외 처리), --- .../onederful/domain/user/dto/RequestDto.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java b/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java index 8f29906..f8ef9ec 100644 --- a/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java +++ b/src/main/java/com/example/onederful/domain/user/dto/RequestDto.java @@ -6,6 +6,7 @@ import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; @@ -14,21 +15,24 @@ @NoArgsConstructor @Getter public class RequestDto { - - @NotBlank(groups = {SignupGroup.class, LoginGroup.class}) + @NotBlank(groups = {SignupGroup.class, LoginGroup.class}, message = "사용자명은 필수입니다.") + @Pattern(groups = {SignupGroup.class, LoginGroup.class}, + regexp = "^[a-zA-Z0-9]{4,20}$", + message = "사용자명은 4-20자의 영문/숫자만 허용됩니다") private String username; - @NotBlank (groups = {SignupGroup.class}) - @Email (groups = {SignupGroup.class}, message = "올바른 형식의 이메일 주소를 입력해주세요") + @NotBlank (groups = {SignupGroup.class} , message = "이메일은 필수입니다.") + @Email (groups = {SignupGroup.class}, message = "유효한 이메일 형식이 아닙니다.") private String email; - @NotBlank (groups = {SignupGroup.class,LoginGroup.class, PasswordGroup.class}) + @NotBlank (groups = {SignupGroup.class,LoginGroup.class, PasswordGroup.class} , message = "비밀번호는 필수입니다.") @Pattern (groups = {SignupGroup.class,LoginGroup.class, PasswordGroup.class}, regexp = "^(?=.*[A-Z])(?=.*[a-z])(?=.*\\d)(?=.*[^\\w\\s]).+$", message = "비밀번호는 대문자·소문자·숫자·특수문자를 각각 1자 이상 포함해야 합니다." ) private String password; - @NotBlank (groups = {SignupGroup.class}) + @NotBlank (groups = {SignupGroup.class}, message = "이름은 필수입니다.") + @Size(groups = {SignupGroup.class}, min = 2, max = 50, message = "이름은 2~50자 사이어야 합니다.") private String name; } From 84bd720a0d6bbe7f063907f0021212212e4fd7e3 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Wed, 18 Jun 2025 19:54:16 +0900 Subject: [PATCH 093/123] =?UTF-8?q?refactor=20:=20=EA=B0=80=EB=8F=85?= =?UTF-8?q?=EC=84=B1=20=ED=96=A5=EC=83=81=EC=9D=84=20=EC=9C=84=ED=95=B4=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/user/repository/UserRepository.java | 4 +++- .../domain/user/service/UserService.java | 15 ++++++++++----- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java b/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java index 731b95d..fa642f7 100644 --- a/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java +++ b/src/main/java/com/example/onederful/domain/user/repository/UserRepository.java @@ -6,6 +6,8 @@ import java.util.Optional; public interface UserRepository extends JpaRepository { - Optional findByEmail(String email); + boolean existsByEmail(String email); + boolean existsByUsername(String username); Optional findByUsername(String username); + } diff --git a/src/main/java/com/example/onederful/domain/user/service/UserService.java b/src/main/java/com/example/onederful/domain/user/service/UserService.java index 80e918c..c8c8075 100644 --- a/src/main/java/com/example/onederful/domain/user/service/UserService.java +++ b/src/main/java/com/example/onederful/domain/user/service/UserService.java @@ -28,11 +28,15 @@ public class UserService { public UserResponseDto signup(RequestDto dto){ // 이메일 중복 확인 - userRepository.findByEmail(dto.getEmail()).ifPresent( - user -> { - throw new CustomException(ErrorCode.DUPLICATE_USER); - } - ); + if(userRepository.existsByEmail(dto.getEmail())){ + throw new CustomException(ErrorCode.DUPLICATE_EMAIL); + } + + + // 아이디 중복 확인 + if(userRepository.existsByUsername(dto.getUsername())){ + throw new CustomException(ErrorCode.DUPLICATE_USER); + } // Dto → Entity User user = UserMapper.user(dto); @@ -52,6 +56,7 @@ public Tokeninfo login(RequestDto dto){ String username = dto.getUsername(); String password = dto.getPassword(); + User user = userRepository.findByUsername(username).orElseThrow( () -> new CustomException(ErrorCode.BAD_REQUEST) ); From 557f8229911a67f1edc411d561e3e5e704f033ee Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 20:43:07 +0900 Subject: [PATCH 094/123] =?UTF-8?q?refactor=20:=20api=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=20PatchMapping->putMapping?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/comment/controller/CommentController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 1d43443..37cc60a 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -35,7 +35,7 @@ public ResponseEntity save(@PathVariable Long task_id, HttpServl } // 댓글 수정 - @PatchMapping("/tasks/{task_id}/comments/{comment_id}") + @PutMapping("/tasks/{task_id}/comments/{comment_id}") public ResponseEntity updateComment( @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody CommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { From 16b55cd9a2663a06840f2a2fee5b06941a02c2f9 Mon Sep 17 00:00:00 2001 From: saevit Date: Wed, 18 Jun 2025 20:44:32 +0900 Subject: [PATCH 095/123] =?UTF-8?q?feat:=20comment=20=EC=83=9D=EC=84=B1,?= =?UTF-8?q?=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20=EC=8B=9C=20?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=EA=B8=B0=EB=A1=9D=EB=90=98=EB=A1=9D=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/LoggingAspect.java | 11 +++--- .../domain/log/controller/LogController.java | 12 ++++--- .../{LogResponseDto.java => LogResponse.java} | 8 ++--- .../domain/log/dto/LogsResponse.java | 17 +++++++++ .../onederful/domain/log/enums/Activity.java | 7 ++-- .../domain/log/service/LogService.java | 35 ++++++++++++++++--- .../onederful/exception/ErrorCode.java | 5 ++- 7 files changed, 72 insertions(+), 23 deletions(-) rename src/main/java/com/example/onederful/domain/log/dto/{LogResponseDto.java => LogResponse.java} (84%) create mode 100644 src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index e050e6f..415944a 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -33,12 +33,15 @@ public void loginMethod() {} @Pointcut( "execution(* com.example..TaskService.createTask(..)) || " + "execution(* com.example..TaskService.updateTask(..)) || " + - "execution(* com.example..TaskService.deleteTask(..))" + "execution(* com.example..TaskService.deleteTask(..)) || " + + "execution(* com.example..CommentService.save(..)) || " + + "execution(* com.example..CommentService.updateComment(..)) || " + + "execution(* com.example..CommentService.deleteComment(..))" ) public void cudMethods() {} - @Pointcut("execution(* com.example..TaskService.updateTask(..))") - public void updateTaskMethod() {} + @Pointcut("execution(* com.example..TaskService.updateTaskStatus(..))") + public void updateTaskStatusMethod() {} // 로그인 @AfterReturning(pointcut = "loginMethod()", returning = "result") @@ -63,7 +66,7 @@ public void logCudMethods(Object result) { } // 상태 변경 - @Around("updateTaskMethod()") + @Around("updateTaskStatusMethod()") public Object logTaskStatusChange(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); Long taskId = (Long) args[0]; // 첫 번째 인자가 taskId diff --git a/src/main/java/com/example/onederful/domain/log/controller/LogController.java b/src/main/java/com/example/onederful/domain/log/controller/LogController.java index 3686074..76bf437 100644 --- a/src/main/java/com/example/onederful/domain/log/controller/LogController.java +++ b/src/main/java/com/example/onederful/domain/log/controller/LogController.java @@ -2,18 +2,17 @@ import java.time.LocalDate; -import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; import org.springframework.format.annotation.DateTimeFormat; -import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.example.onederful.domain.log.dto.LogResponseDto; +import com.example.onederful.common.ApiResponseDto; +import com.example.onederful.domain.log.dto.LogsResponse; import com.example.onederful.domain.log.service.LogService; import lombok.RequiredArgsConstructor; @@ -37,7 +36,7 @@ public class LogController { * @return 조회된 활동 로그 */ @GetMapping("/api/activities") - public ResponseEntity> getLog( + public ResponseEntity getLog( @RequestParam(required = false) Long userId, @RequestParam(required = false) String activity, @RequestParam(required = false) Long targetId, @@ -45,6 +44,9 @@ public ResponseEntity> getLog( @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end, @PageableDefault(page = 0, size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable ) { - return new ResponseEntity<>(logService.getLog(userId, activity, targetId, start, end, pageable), HttpStatus.OK); + + LogsResponse response = logService.findLog(userId, activity, targetId, start, end, pageable); + + return ResponseEntity.ok(ApiResponseDto.success("활동 로그 리스트 조회에 성공하였습니다.", response)); } } diff --git a/src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java b/src/main/java/com/example/onederful/domain/log/dto/LogResponse.java similarity index 84% rename from src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java rename to src/main/java/com/example/onederful/domain/log/dto/LogResponse.java index f738838..10ec211 100644 --- a/src/main/java/com/example/onederful/domain/log/dto/LogResponseDto.java +++ b/src/main/java/com/example/onederful/domain/log/dto/LogResponse.java @@ -7,14 +7,14 @@ import lombok.Getter; @Getter -public class LogResponseDto { +public class LogResponse { LocalDateTime createdAt; String userName; String activityStr; Long targetID; String logMessage; - public LogResponseDto( + public LogResponse( LocalDateTime createdAt, String userName, String activityStr, @@ -28,8 +28,8 @@ public LogResponseDto( this.logMessage = logMessage; } - public static LogResponseDto of(Log log) { - return new LogResponseDto( + public static LogResponse of(Log log) { + return new LogResponse( log.getCreatedAt(), log.getUser().getName(), log.getActivity().toString(), diff --git a/src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java b/src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java new file mode 100644 index 0000000..fc74102 --- /dev/null +++ b/src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java @@ -0,0 +1,17 @@ +package com.example.onederful.domain.log.dto; + +import java.util.List; + +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class LogsResponse { + + private List content; + private Long totalElements; + private Long totalPages; + private Long size; + private Long number; +} diff --git a/src/main/java/com/example/onederful/domain/log/enums/Activity.java b/src/main/java/com/example/onederful/domain/log/enums/Activity.java index eef3197..e6d0ad6 100644 --- a/src/main/java/com/example/onederful/domain/log/enums/Activity.java +++ b/src/main/java/com/example/onederful/domain/log/enums/Activity.java @@ -6,10 +6,9 @@ public enum Activity { TASK_DELETED("작업이 삭제되었습니다."), TASK_STATUS_TODO_TO_IN_PROGRESS("작업이 TODO에서 IN_PROGRESS로 변경되었습니다."), TASK_STATUS_IN_PROGRESS_TO_DONE("작업이 IN_PROGRESS에서 DONE으로 변경되었습니다."), - TASK_STATUS_TODO_TO_DONE("작업이 TODO에서 DONE으로 변경되었습니다."), - // COMMENT_CREATED, - // COMMENT_UPDATED, - // COMMENT_DELETED, + COMMENT_CREATED("새로운 댓글이 생성되었습니다."), + COMMENT_UPDATED("댓글이 수정되었습니다."), + COMMENT_DELETED("댓글이 삭제되었습니다."), USER_LOGGED_IN("로그인 하였습니다."); // USER_LOGGED_OUT("로그아웃 하였습니다.") diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index aee3a9c..1a0b404 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -1,13 +1,16 @@ package com.example.onederful.domain.log.service; import java.time.LocalDate; +import java.util.stream.Collectors; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.domain.Specification; import org.springframework.stereotype.Service; -import com.example.onederful.domain.log.dto.LogResponseDto; +import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; +import com.example.onederful.domain.log.dto.LogResponse; +import com.example.onederful.domain.log.dto.LogsResponse; import com.example.onederful.domain.log.entity.Log; import com.example.onederful.domain.log.enums.Activity; import com.example.onederful.domain.log.enums.Method; @@ -32,7 +35,7 @@ public class LogService { private final UserRepository userRepositry; private final JwtUtil jwtUtil; - public Page getLog( + public LogsResponse findLog( Long userId, String activityStr, Long targetId, LocalDate start, LocalDate end, Pageable pageable) { @@ -44,8 +47,15 @@ public Page getLog( .and(LogSpecification.hasTargetId(targetId)) .and(LogSpecification.betweenDates(start, end)); - return logRepository.findAll(spec, pageable) - .map(LogResponseDto::of); + Page logs = logRepository.findAll(spec, pageable); + + return LogsResponse.builder() + .content(logs.getContent().stream().map(LogResponse::of).collect(Collectors.toList())) + .totalElements(logs.getTotalElements()) + .size((long) logs.getSize()) + .number((long) logs.getNumber()) + .totalPages((long) logs.getTotalPages()) + .build(); } @Transactional @@ -57,7 +67,16 @@ public void saveCudLog(String ip, Method method, String url, Long userId, Object // 활동 유형 -> 요청 메서드와 url로 일치하는 활동 유형 찾기 Activity activity = null; - if (method.equals(Method.POST) && url.contains("/tasks")) { + if (method.equals(Method.POST) && url.contains("/comments")) { + activity = Activity.COMMENT_CREATED; + } + else if (method.equals(Method.PUT) && url.contains("/comments")) { + activity = Activity.COMMENT_UPDATED; + } + else if (method.equals(Method.DELETE) && url.contains("/comments")) { + activity = Activity.COMMENT_DELETED; + } + else if (method.equals(Method.POST) && url.contains("/tasks")) { activity = Activity.TASK_CREATED; } else if (method.equals(Method.PUT) && url.contains("/tasks")) { @@ -67,6 +86,7 @@ else if (method.equals(Method.DELETE) && url.contains("/tasks")) { activity = Activity.TASK_DELETED; } + // 대상 id -> 생성인 경우 응답에서 / 수정과 삭제의 경우 url 마지막에서 찾기 Long targetId = null; if (activity.equals(Activity.TASK_CREATED)) { @@ -74,6 +94,11 @@ else if (method.equals(Method.DELETE) && url.contains("/tasks")) { targetId = ((TaskResponse) result).getId(); } } + else if (activity.equals(Activity.COMMENT_CREATED)) { + if (result instanceof CreateCommentResponseDataDto) { + targetId = ((CreateCommentResponseDataDto) result).getId(); + } + } else { String[] parts = url.split("/"); String lastPart = parts[parts.length - 1]; // /api/.../{id}의 id diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index 2c3e396..1620cda 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -22,7 +22,10 @@ public enum ErrorCode { // Comment NONEXISTENT_COMMENT(HttpStatus.BAD_REQUEST, "존재하지 않는 댓글입니다."), - INVALID_COMMENT(HttpStatus.BAD_REQUEST, "삭제된 댓글입니다."); + INVALID_COMMENT(HttpStatus.BAD_REQUEST, "삭제된 댓글입니다."), + + // Log + INVALID_OR_EXPIRED_REQUEST(HttpStatus.BAD_REQUEST,"요청 정보가 유효하지 않거나 만료되었습니다."); private final HttpStatus status; private final String message; From 1f015854caed29f9661e07ae5d61bebe2c5c894e Mon Sep 17 00:00:00 2001 From: saevit Date: Wed, 18 Jun 2025 21:17:03 +0900 Subject: [PATCH 096/123] =?UTF-8?q?feat:=20=EB=A1=9C=EA=B7=B8=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20=EC=9E=98=EB=AA=BB=EB=90=9C=20=ED=99=9C?= =?UTF-8?q?=EB=8F=99=20=EC=9C=A0=ED=98=95=EC=97=90=20=EB=8C=80=ED=95=9C=20?= =?UTF-8?q?=EC=98=88=EC=99=B8=20=EC=B2=98=EB=A6=AC=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/service/LogService.java | 10 +++++++++- .../com/example/onederful/exception/ErrorCode.java | 4 +++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index 1a0b404..1bea216 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -39,8 +39,16 @@ public LogsResponse findLog( Long userId, String activityStr, Long targetId, LocalDate start, LocalDate end, Pageable pageable) { + Activity activity = null; + try { + if (activityStr != null) { + activity = Activity.valueOf(activityStr); + } + } catch (IllegalArgumentException e) { + throw new CustomException(ErrorCode.INVALID_ACTIVITY); + } + // 들어온 조건 여부로 동적 쿼리 설정 - Activity activity = (activityStr != null) ? Activity.valueOf(activityStr) : null; Specification spec = LogSpecification.hasUserId(userId) .and(LogSpecification.hasActivity(activity)) diff --git a/src/main/java/com/example/onederful/exception/ErrorCode.java b/src/main/java/com/example/onederful/exception/ErrorCode.java index 1620cda..3ca6889 100644 --- a/src/main/java/com/example/onederful/exception/ErrorCode.java +++ b/src/main/java/com/example/onederful/exception/ErrorCode.java @@ -25,7 +25,9 @@ public enum ErrorCode { INVALID_COMMENT(HttpStatus.BAD_REQUEST, "삭제된 댓글입니다."), // Log - INVALID_OR_EXPIRED_REQUEST(HttpStatus.BAD_REQUEST,"요청 정보가 유효하지 않거나 만료되었습니다."); + INVALID_OR_EXPIRED_REQUEST(HttpStatus.BAD_REQUEST,"요청 정보가 유효하지 않거나 만료되었습니다."), + INVALID_ACTIVITY(HttpStatus.BAD_REQUEST,"알 수 없는 활동 유형입니다."); + private final HttpStatus status; private final String message; From a15c5a194762422329fbf95c3ec69e84dba82ec5 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Thu, 19 Jun 2025 02:28:04 +0900 Subject: [PATCH 097/123] =?UTF-8?q?test:=20dashboard=20repository=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/DashboardRepositoryTest.java | 237 ++++++++++++++++++ 1 file changed, 237 insertions(+) create mode 100644 src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java diff --git a/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java b/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java new file mode 100644 index 0000000..dc9a031 --- /dev/null +++ b/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java @@ -0,0 +1,237 @@ +package com.example.onederful.domain.dashboard.repository; + +import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.task.repository.TaskRepository; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.enums.Role; +import com.example.onederful.domain.user.repository.UserRepository; +import jakarta.persistence.EntityManager; +import jakarta.transaction.Transactional; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import java.util.List; + +import static org.assertj.core.api.Assertions.as; +import static org.assertj.core.api.Assertions.assertThat; + + +import java.time.LocalDateTime; + +@SpringBootTest +@ActiveProfiles("test") +@Transactional +public class DashboardRepositoryTest { + + @Autowired + private EntityManager em; + + @Autowired + private TaskRepository taskRepository; + + @Autowired + private UserRepository userRepository; + + private DashboardRepositoryImpl dashboardRepository; + + private User user; + + @Test + void 통계_정보_조회_성공(){ + //given + dashboardRepository = new DashboardRepositoryImpl(em); + + user = User.builder() + .username("iamgroot") + .email("iamgroot@example.com") + .password("Password123!") + .name("groot") + .role(Role.USER) + .build(); + + userRepository.save(user); + + taskRepository.save(Task.builder() + .title("Task1") + .description("Task1 Content") + .priority(Priority.HIGH) + .assignee(user) + .user(user) + .status(ProcessStatus.TODO) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().plusDays(1)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task2") + .description("Task2 Content") + .priority(Priority.MEDIUM) + .assignee(user) + .user(user) + .status(ProcessStatus.IN_PROGRESS) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now()) + .dueDate(LocalDateTime.now().minusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task3") + .description("Task3 Content") + .priority(Priority.HIGH) + .assignee(user) + .user(user) + .status(ProcessStatus.DONE) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().minusDays(1)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task4") + .description("Task4 Content") + .priority(Priority.LOW) + .assignee(user) + .user(user) + .status(ProcessStatus.TODO) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().plusDays(1)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task5") + .description("Task5 Content") + .priority(Priority.LOW) + .assignee(user) + .user(user) + .status(ProcessStatus.DONE) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().minusDays(2)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + //when + StatisticsResponseDto result = dashboardRepository.getStatistics(); + + //then + assertThat(result.getTotalTaskCount()).isEqualTo(5); + assertThat(result.getTodoTaskCount()).isEqualTo(2); + assertThat(result.getInProgressTaskCount()).isEqualTo(1); + assertThat(result.getDoneTaskCount()).isEqualTo(2); + assertThat(result.getOverdueTaskCount()).isEqualTo(1); + assertThat(result.getTaskDoneRate()).isEqualTo(40.0); + } + + @Test + void 오늘_내_태스크_조회(){ + //given + dashboardRepository = new DashboardRepositoryImpl(em); + + user = User.builder() + .username("iamgroot") + .email("iamgroot@example.com") + .password("Password123!") + .name("groot") + .role(Role.USER) + .build(); + + userRepository.save(user); + + taskRepository.save(Task.builder() + .title("Task1") + .description("Task1 Content") + .priority(Priority.LOW) + .assignee(user) + .user(user) + .status(ProcessStatus.TODO) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now()) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task2") + .description("Task2 Content") + .priority(Priority.HIGH) + .assignee(user) + .user(user) + .status(ProcessStatus.TODO) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now()) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + + taskRepository.save(Task.builder() + .title("Task3") + .description("Task3 Content") + .priority(Priority.MEDIUM) + .assignee(user) + .user(user) + .status(ProcessStatus.IN_PROGRESS) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now()) + .dueDate(LocalDateTime.now().minusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task4") + .description("Task4 Content") + .priority(Priority.HIGH) + .assignee(user) + .user(user) + .status(ProcessStatus.DONE) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().minusDays(1)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + taskRepository.save(Task.builder() + .title("Task5") + .description("Task5 Content") + .priority(Priority.LOW) + .assignee(user) + .user(user) + .status(ProcessStatus.DONE) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().minusDays(2)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build() + ); + + //when + List taskList = dashboardRepository.getMyTasksToday(user.getId()); + + //then + assertThat(taskList).hasSize(3); + assertThat(taskList.get(0).getPriority()).isEqualTo(Priority.HIGH); + assertThat(taskList.get(1).getPriority()).isEqualTo(Priority.MEDIUM); + assertThat(taskList.get(2).getPriority()).isEqualTo(Priority.LOW); + + } + +} From e1c3813dbfd873744d81153a7ae1d3d0495fcb86 Mon Sep 17 00:00:00 2001 From: kimminsung Date: Thu, 19 Jun 2025 02:28:34 +0900 Subject: [PATCH 098/123] =?UTF-8?q?test:=20dashboard=20service=20=ED=85=8C?= =?UTF-8?q?=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/DashboardServiceTest.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/test/java/com/example/onederful/domain/dashboard/service/DashboardServiceTest.java diff --git a/src/test/java/com/example/onederful/domain/dashboard/service/DashboardServiceTest.java b/src/test/java/com/example/onederful/domain/dashboard/service/DashboardServiceTest.java new file mode 100644 index 0000000..34cdb49 --- /dev/null +++ b/src/test/java/com/example/onederful/domain/dashboard/service/DashboardServiceTest.java @@ -0,0 +1,103 @@ +package com.example.onederful.domain.dashboard.service; +import static org.assertj.core.api.Assertions.*; +import static org.mockito.BDDMockito.*; + +import com.example.onederful.domain.dashboard.dto.MyTasksTodayResponseDto; +import com.example.onederful.domain.dashboard.dto.StatisticsResponseDto; +import com.example.onederful.domain.dashboard.repository.DashboardRepository; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.Priority; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.enums.Role; +import com.example.onederful.domain.user.repository.UserRepository; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import java.util.Optional; +import java.util.List; +import java.time.LocalDateTime; + + +@ExtendWith(MockitoExtension.class) +public class DashboardServiceTest { + @InjectMocks + private DashboardService dashboardService; + + @Mock + private DashboardRepository dashboardRepository; + + @Mock + private UserRepository userRepository; + + private User user; + private Task task; + @Test + void 통계_정보_조회_성공(){ + //given + StatisticsResponseDto statisticsResponseDto = + StatisticsResponseDto.builder() + .totalTaskCount(5L) + .todoTaskCount(2L) + .inProgressTaskCount(1L) + .doneTaskCount(2L) + .taskDoneRate(40.0) + .overdueTaskCount(1L) + .build(); + + given(dashboardRepository.getStatistics()).willReturn(statisticsResponseDto); + + //when + StatisticsResponseDto actualResult = dashboardService.getStatistics(); + + //then + assertThat(actualResult.getTotalTaskCount()).isEqualTo(5L); + assertThat(actualResult.getTodoTaskCount()).isEqualTo(2L); + assertThat(actualResult.getInProgressTaskCount()).isEqualTo(1L); + assertThat(actualResult.getDoneTaskCount()).isEqualTo(2L); + assertThat(actualResult.getTaskDoneRate()).isEqualTo(40.0); + } + + @Test + void 오늘_내_태스크_조회_성공(){ + //given + + user = User.builder() + .username("iamgroot") + .email("iamgroot@example.com") + .password("Password123!") + .name("groot") + .role(Role.USER) + .build(); + + task = Task.builder() + .title("Task1") + .description("Task1 Content") + .priority(Priority.HIGH) + .assignee(user) + .user(user) + .status(ProcessStatus.TODO) + .createdAt(LocalDateTime.now()) + .updatedAt(LocalDateTime.now()) + .startedAt(LocalDateTime.now().plusDays(1)) + .dueDate(LocalDateTime.now().plusDays(5)) + .build(); + + given(userRepository.findById(1L)).willReturn(Optional.of(user)); + given(dashboardRepository.getMyTasksToday(1L)).willReturn(List.of(task)); + + //when + List actualResult = dashboardService.getMyTasksToday(1L); + + //then + assertThat(actualResult).hasSize(1); + MyTasksTodayResponseDto myTasksTodayResponseDto = actualResult.get(0); + assertThat(myTasksTodayResponseDto.getId()).isEqualTo(task.getId()); + assertThat(myTasksTodayResponseDto.getContents()).isEqualTo(task.getDescription()); + assertThat(myTasksTodayResponseDto.getManagerId()).isEqualTo(user.getId()); + + } +} From a6373c15ba497a25ce8f28134856d81137afcf26 Mon Sep 17 00:00:00 2001 From: saevit Date: Thu, 19 Jun 2025 09:55:28 +0900 Subject: [PATCH 099/123] =?UTF-8?q?comment:=20log=20=EB=8F=84=EB=A9=94?= =?UTF-8?q?=EC=9D=B8=20=EC=A3=BC=EC=84=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/LoggingAspect.java | 6 +- .../log/repository/LogSpecification.java | 4 ++ .../domain/log/service/LogService.java | 71 ++++++++++--------- 3 files changed, 45 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index 415944a..fb9e713 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -43,7 +43,7 @@ public void cudMethods() {} @Pointcut("execution(* com.example..TaskService.updateTaskStatus(..))") public void updateTaskStatusMethod() {} - // 로그인 + // 로그인 시 자동 로그 기록 @AfterReturning(pointcut = "loginMethod()", returning = "result") public void logLoginMethod(Object result) { @@ -54,7 +54,7 @@ public void logLoginMethod(Object result) { logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); } - // 생성, 수정, 삭제 + // 생성, 수정, 삭제 시 자동 로그 기록 @AfterReturning(pointcut = "cudMethods()", returning = "result") public void logCudMethods(Object result) { @@ -65,7 +65,7 @@ public void logCudMethods(Object result) { logService.saveCudLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), result); } - // 상태 변경 + // 상태 변경 시 자동 로그 기록 @Around("updateTaskStatusMethod()") public Object logTaskStatusChange(ProceedingJoinPoint joinPoint) throws Throwable { Object[] args = joinPoint.getArgs(); diff --git a/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java b/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java index e08c42d..a0c035c 100644 --- a/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java +++ b/src/main/java/com/example/onederful/domain/log/repository/LogSpecification.java @@ -8,21 +8,25 @@ import com.example.onederful.domain.log.enums.Activity; public class LogSpecification { + // userId를 통한 검색 조건 (WHERE userId = ?) public static Specification hasUserId(Long userId) { return (root, query, builder) -> userId == null ? null : builder.equal(root.get("user").get("id"), userId); } + // activity를 통한 검색 조건 (WHERE activity = ?) public static Specification hasActivity(Activity activity) { return (root, query, builder) -> activity == null ? null : builder.equal(root.get("activity"), activity); } + // targetId를 통한 검색 조건 (WHERE targetId = ?) public static Specification hasTargetId(Long targetId) { return (root, query, builder) -> targetId == null ? null : builder.equal(root.get("targetId"), targetId); } + // 날짜를 통한 검색 조건 (WHERE ? BETWEEN start and end) public static Specification betweenDates(LocalDate start, LocalDate end) { return (root, query, builder) -> { // 둘다 없을 경우 diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index 1bea216..d644ecf 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -35,10 +35,12 @@ public class LogService { private final UserRepository userRepositry; private final JwtUtil jwtUtil; + // log 조회 메서드 public LogsResponse findLog( Long userId, String activityStr, Long targetId, LocalDate start, LocalDate end, Pageable pageable) { + // 활동 유형 Enum 형태로 변환 Activity activity = null; try { if (activityStr != null) { @@ -66,6 +68,41 @@ public LogsResponse findLog( .build(); } + // 로그인 시 로그 기록 + @Transactional + public void saveLoginLog(String ip, Method method, String url, Object result) { + // userId + Long userId = null; + if (result instanceof Tokeninfo) { + String token = ((Tokeninfo) result).getToken(); + userId = jwtUtil.extractAllClaims(token).get("id", Long.class); + } + + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + // 활동 유형 + Activity activity = Activity.USER_LOGGED_IN; + + // 대상 id + Long targetId = userId; + + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } + + // 생성, 수정, 삭제 시 로그 기록 @Transactional public void saveCudLog(String ip, Method method, String url, Long userId, Object result) { // 현재 유저 조회 @@ -126,39 +163,7 @@ else if (activity.equals(Activity.COMMENT_CREATED)) { logRepository.save(log); } - @Transactional - public void saveLoginLog(String ip, Method method, String url, Object result) { - // userId - Long userId = null; - if (result instanceof Tokeninfo) { - String token = ((Tokeninfo) result).getToken(); - userId = jwtUtil.extractAllClaims(token).get("id", Long.class); - } - - // 현재 유저 조회 - User user = userRepositry.findById(userId).orElseThrow( - () -> new CustomException(ErrorCode.UNAUTHORIZED) - ); - - // 활동 유형 - Activity activity = Activity.USER_LOGGED_IN; - - // 대상 id - Long targetId = userId; - - // 로그 DB에 저장 - Log log = Log.builder() - .user(user) - .activity(activity) - .ipAddress(ip) - .method(method) - .targetId(targetId) - .requestUrl(url) - .build(); - - logRepository.save(log); - } - + // 상태 변경 시 로그 기록 public void saveTaskStatusChangeLog(String ip, Method method, String url, Long userId, Long targetId, Activity activity) { // 현재 유저 조회 User user = userRepositry.findById(userId).orElseThrow( From 85c8ed1fa9c9a83b8c76ceb546ea98628885445e Mon Sep 17 00:00:00 2001 From: doohaaa Date: Wed, 18 Jun 2025 22:00:08 +0900 Subject: [PATCH 100/123] =?UTF-8?q?feat=20:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20testCode=20=EA=B5=AC=ED=98=84=20(line=20coverage=2022%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/service/CommentServiceTest.java | 109 ++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java diff --git a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java new file mode 100644 index 0000000..7e16df9 --- /dev/null +++ b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java @@ -0,0 +1,109 @@ +package com.example.onederful.domain.comment.service; + +import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; +import com.example.onederful.domain.comment.entity.Comment; +import com.example.onederful.domain.comment.repository.CommentRepository; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.repository.TaskRepository; +import com.example.onederful.domain.user.entity.User; +import com.example.onederful.domain.user.repository.UserRepository; +import com.example.onederful.security.JwtUtil; +import jakarta.servlet.http.HttpServletRequest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; +import org.springframework.http.HttpStatus; + +import java.util.Optional; + +import static org.assertj.core.api.Assertions.assertThat; + + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; + +@ExtendWith(MockitoExtension.class) +class CommentServiceTest { + @Mock + private CommentRepository commentRepository; + @Mock + private UserRepository userRepository; + @Mock + private TaskRepository taskRepository; + @Mock + private JwtUtil jwtUtil; + + @InjectMocks + private CommentService commentService; + + @Test + @DisplayName("지정된 테스크에 HttpServletRequest에서 사용자 정보를 가져와서 댓글을 생성 할 수 있는지") + void save() { + + // given + Long task_id = 5L; + Long user_id = 2L; + HttpServletRequest httpServletRequest = mock(HttpServletRequest.class); + String content = "댓글 생성 테스트"; + + User user = mock(User.class); + Task task = mock(Task.class); + Comment comment = Comment.builder() + .id(1L) + .content(content) + .user(user) + .task(task) + .build(); + + + given(jwtUtil.extractId(httpServletRequest)).willReturn(user_id); + + given(userRepository.findById(user_id)).willReturn(Optional.of(user)); + given(taskRepository.findById(task_id)).willReturn(Optional.of(task)); + given(commentRepository.save(any(Comment.class))).willReturn(comment); + // when + CreateCommentResponseDataDto result = commentService.save(task_id, httpServletRequest, content); + + // then + assertThat(result.getContent()).isEqualTo(content); + assertThat(result.getId()).isEqualTo(1L); + + } + + @Test + @DisplayName("새로운 댓글내용 입력했을때 그 값으로 변하는지 안하는지") + void updateComment() { + // given + + + + // when + + + // then + + + + + } + + @Test + void findAllCommentByTaskId() { + } + + @Test + void findAllCommentByTaskIdInPage() { + } + + @Test + void findCommentByContent() { + } + + @Test + void deleteComment() { + } +} \ No newline at end of file From 4e750e93bd65ecb64df9d21d550ab173d5c4ef06 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Thu, 19 Jun 2025 09:56:01 +0900 Subject: [PATCH 101/123] =?UTF-8?q?feat=20:=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?UTF-8?q?=20testCode=20=EA=B5=AC=ED=98=84=20(line=20coverage=2058%)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/service/CommentServiceTest.java | 44 +++++++++++++++++-- 1 file changed, 40 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java index 7e16df9..e77fbbc 100644 --- a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java +++ b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java @@ -1,6 +1,7 @@ package com.example.onederful.domain.comment.service; import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; +import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; import com.example.onederful.domain.task.entity.Task; @@ -17,6 +18,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import org.springframework.http.HttpStatus; +import java.time.LocalDateTime; import java.util.Optional; import static org.assertj.core.api.Assertions.assertThat; @@ -78,16 +80,34 @@ void save() { @DisplayName("새로운 댓글내용 입력했을때 그 값으로 변하는지 안하는지") void updateComment() { // given + Long taskId = 5L; + Long commentId = 1L; + Long userId = 10L; + String originalContent = "기존 댓글 입니다."; + String updatedContent = " 수정된 댓글 입니다."; + HttpServletRequest httpServletRequest = mock(HttpServletRequest.class); + Task task = mock(Task.class); + User user = mock(User.class); + Comment comment = Comment.builder() + .id(commentId) + .content(originalContent) + .user(user) + .task(task) + .isDeleted(false) + .build(); + given(taskRepository.findById(taskId)).willReturn(Optional.of(task)); + given(commentRepository.findById(commentId)).willReturn(Optional.of(comment)); + given(jwtUtil.extractId(httpServletRequest)).willReturn(userId); + given(userRepository.findById(userId)).willReturn(Optional.of(user)); // when - + UpdateCommentResponseDataDto result = commentService.updateComment(taskId, commentId, updatedContent, httpServletRequest); // then - - - + assertThat(result.getContent()).isEqualTo(updatedContent); + assertThat(result.getUpdated_at()).isNotNull(); } @@ -104,6 +124,22 @@ void findCommentByContent() { } @Test + @DisplayName("댓글이 삭제 되는지") void deleteComment() { + // given + Long commentId = 1L; + LocalDateTime later = LocalDateTime.now().plusMinutes(1); + Comment comment = Comment.builder() + .id(commentId) + .isDeleted(false) + .build(); + given(commentRepository.findById(commentId)).willReturn(Optional.of(comment)); + + // when + commentService.deleteComment(commentId); + + // then + assertThat(comment.getIsDeleted()).isEqualTo(true); + assertThat(comment.getDeletedAt()).isBefore(later); } } \ No newline at end of file From 88c74463af0a8bd48de5eb9eded04de8fd7dd5c5 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Thu, 19 Jun 2025 10:10:45 +0900 Subject: [PATCH 102/123] =?UTF-8?q?feat=20:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../user/controller/AuthController.java | 23 +++++++++++--- .../domain/user/service/UserService.java | 30 +++++++++++++++++-- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java index 844f203..6590f32 100644 --- a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -4,25 +4,29 @@ import com.example.onederful.domain.user.common.LoginGroup; import com.example.onederful.domain.user.common.PasswordGroup; import com.example.onederful.domain.user.common.SignupGroup; +import com.example.onederful.domain.user.common.UserMapper; import com.example.onederful.domain.user.dto.*; import com.example.onederful.domain.user.service.UserService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; +import org.apache.coyote.RequestInfo; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.List; + @RestController @RequiredArgsConstructor @RequestMapping("/api") public class AuthController { private final UserService userService; - + // 회원가입 @PostMapping("/auth/register") - public ResponseEntity register(@Validated(SignupGroup.class) @RequestBody RequestDto requestDto){ + public ResponseEntity register(@Validated(SignupGroup.class) @RequestBody RequestDto requestDto){ UserResponseDto signup = userService.signup(requestDto); @@ -33,7 +37,7 @@ public ResponseEntity register(@Validated(SignupGroup.class) @Re // 로그인 @PostMapping("/auth/login") - public ResponseEntity login(@Validated(LoginGroup.class) @RequestBody RequestDto requestDto){ + public ResponseEntity login(@Validated(LoginGroup.class) @RequestBody RequestDto requestDto){ Tokeninfo token = userService.login(requestDto); @@ -56,7 +60,7 @@ public ResponseEntity select (HttpServletRequest request){ // 회원 탈퇴 (계정 삭제) @PostMapping("/auth/withdraw") public ResponseEntity withdraw (HttpServletRequest request, - @Validated(PasswordGroup.class) @RequestBody RequestDto dto){ + @Validated(PasswordGroup.class) @RequestBody RequestDto dto){ userService.withdraw(request,dto); @@ -65,5 +69,16 @@ public ResponseEntity withdraw (HttpServletRequest request, return ResponseEntity.status(HttpStatus.OK).body(success); } + // 모든 회원 정보 조회 + @GetMapping("/users") + public ResponseEntity selectAll(){ + List selectAll = userService.selectAll(); + + ApiResponseDto success = ApiResponseDto.success("요청이 성공적으로 처리되었습니다.",selectAll); + + return ResponseEntity.status(HttpStatus.OK).body(success); + } + + } diff --git a/src/main/java/com/example/onederful/domain/user/service/UserService.java b/src/main/java/com/example/onederful/domain/user/service/UserService.java index c8c8075..4e1520f 100644 --- a/src/main/java/com/example/onederful/domain/user/service/UserService.java +++ b/src/main/java/com/example/onederful/domain/user/service/UserService.java @@ -15,6 +15,9 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.util.ArrayList; +import java.util.List; + @Service @RequiredArgsConstructor public class UserService { @@ -23,8 +26,9 @@ public class UserService { private final UserRepository userRepository; private final JwtUtil jwtUtil; - @Transactional + // 회원가입 + @Transactional public UserResponseDto signup(RequestDto dto){ // 이메일 중복 확인 @@ -72,8 +76,9 @@ public Tokeninfo login(RequestDto dto){ return token(token); } - @Transactional + // 회원 정보 조회 + @Transactional public UserResponseDto select(HttpServletRequest request){ // 토큰에서 Id 가져오기 @@ -86,8 +91,9 @@ public UserResponseDto select(HttpServletRequest request){ return UserMapper.data(user); } - @Transactional + // 회원 탈퇴 + @Transactional public void withdraw(HttpServletRequest request , RequestDto dto){ // 토큰에서 Id 가져오기 Long userId = jwtUtil.extractId(request); @@ -107,6 +113,24 @@ public void withdraw(HttpServletRequest request , RequestDto dto){ } + // 모든 회원 정보 조회 + public List selectAll(){ + + List result = new ArrayList<>(); + + List all = userRepository.findAll(); + + for(User user : all){ + result.add(UserMapper.data(user)); + } + + return result; + + } + + + + // ResponseBody date (Token) private Tokeninfo token (String token){ From 096a18b5ec7b25bd8e274574a9b67bb2f6643c4f Mon Sep 17 00:00:00 2001 From: DongGeun Date: Thu, 19 Jun 2025 10:11:25 +0900 Subject: [PATCH 103/123] =?UTF-8?q?feat=20:=20=EB=AA=A8=EB=93=A0=20?= =?UTF-8?q?=ED=9A=8C=EC=9B=90=20=EC=A1=B0=ED=9A=8C=20=EA=B8=B0=EB=8A=A5=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/user/controller/AuthController.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java index 6590f32..f53a8be 100644 --- a/src/main/java/com/example/onederful/domain/user/controller/AuthController.java +++ b/src/main/java/com/example/onederful/domain/user/controller/AuthController.java @@ -4,12 +4,10 @@ import com.example.onederful.domain.user.common.LoginGroup; import com.example.onederful.domain.user.common.PasswordGroup; import com.example.onederful.domain.user.common.SignupGroup; -import com.example.onederful.domain.user.common.UserMapper; import com.example.onederful.domain.user.dto.*; import com.example.onederful.domain.user.service.UserService; import jakarta.servlet.http.HttpServletRequest; import lombok.RequiredArgsConstructor; -import org.apache.coyote.RequestInfo; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; From fa30e771c206c808f47952fead9984dfa13cf66b Mon Sep 17 00:00:00 2001 From: saevit Date: Thu, 19 Jun 2025 10:56:54 +0900 Subject: [PATCH 104/123] =?UTF-8?q?feat:=20=EC=98=88=EC=99=B8=20CustomExce?= =?UTF-8?q?ption=20=EC=82=AC=EC=9A=A9=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/onederful/domain/log/HttpRequestUtil.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java index f4ce47a..1c955a2 100644 --- a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java +++ b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java @@ -5,6 +5,8 @@ import org.springframework.web.context.request.ServletRequestAttributes; import com.example.onederful.domain.log.enums.Method; +import com.example.onederful.exception.CustomException; +import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; @@ -22,11 +24,11 @@ public class HttpRequestUtil { public RequestInfo getRequestInfo() { ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); if (attrs == null) { - throw new IllegalStateException("Request attributes not found"); + throw new CustomException(ErrorCode.INVALID_OR_EXPIRED_REQUEST); } HttpServletRequest request = attrs.getRequest(); if (request == null) { - throw new IllegalStateException("HttpServletRequest not found"); + throw new CustomException(ErrorCode.INVALID_OR_EXPIRED_REQUEST); } // 요청한 사용자의 ip From 093b3e3d1f33606696694e0b5375a43e3dec4128 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Thu, 19 Jun 2025 11:15:33 +0900 Subject: [PATCH 105/123] =?UTF-8?q?test:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/service/CommentServiceTest.java | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java index e77fbbc..9d5ba8a 100644 --- a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java +++ b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java @@ -111,18 +111,6 @@ void updateComment() { } - @Test - void findAllCommentByTaskId() { - } - - @Test - void findAllCommentByTaskIdInPage() { - } - - @Test - void findCommentByContent() { - } - @Test @DisplayName("댓글이 삭제 되는지") void deleteComment() { From e50919f1b7df641efdcc63059b32631acc24cd3f Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 11:30:09 +0900 Subject: [PATCH 106/123] =?UTF-8?q?refactor=20:=20Pagination=20=EA=B3=B5?= =?UTF-8?q?=ED=86=B5=20=EC=9D=91=EB=8B=B5=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../example/onederful/common/ListResponse.java | 16 ++++++++++++++++ .../onederful/domain/comment/controller/.gitkeep | 0 .../onederful/domain/comment/dto/.gitkeep | 0 .../onederful/domain/comment/repository/.gitkeep | 0 .../onederful/domain/comment/service/.gitkeep | 0 .../domain/task/dto/response/CommonResponse.java | 15 --------------- .../domain/task/dto/response/TasksResponse.java | 16 ---------------- 7 files changed, 16 insertions(+), 31 deletions(-) create mode 100644 src/main/java/com/example/onederful/common/ListResponse.java delete mode 100644 src/main/java/com/example/onederful/domain/comment/controller/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/comment/repository/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/comment/service/.gitkeep delete mode 100644 src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java delete mode 100644 src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java diff --git a/src/main/java/com/example/onederful/common/ListResponse.java b/src/main/java/com/example/onederful/common/ListResponse.java new file mode 100644 index 0000000..445eb08 --- /dev/null +++ b/src/main/java/com/example/onederful/common/ListResponse.java @@ -0,0 +1,16 @@ +package com.example.onederful.common; + +import java.util.List; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +public class ListResponse { + + private List content; + private Long totalElements; + private int totalPages; + private int size; + private int number; +} diff --git a/src/main/java/com/example/onederful/domain/comment/controller/.gitkeep b/src/main/java/com/example/onederful/domain/comment/controller/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/comment/dto/.gitkeep b/src/main/java/com/example/onederful/domain/comment/dto/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/comment/repository/.gitkeep b/src/main/java/com/example/onederful/domain/comment/repository/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/comment/service/.gitkeep b/src/main/java/com/example/onederful/domain/comment/service/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java b/src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java deleted file mode 100644 index b308a5e..0000000 --- a/src/main/java/com/example/onederful/domain/task/dto/response/CommonResponse.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.example.onederful.domain.task.dto.response; - -import java.time.OffsetDateTime; -import lombok.AllArgsConstructor; -import lombok.Getter; - -@Getter -@AllArgsConstructor(staticName = "create") -public class CommonResponse { - - private boolean success; - private String message; - private T data; - private OffsetDateTime timestamp; -} diff --git a/src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java b/src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java deleted file mode 100644 index 7a2f6dc..0000000 --- a/src/main/java/com/example/onederful/domain/task/dto/response/TasksResponse.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.example.onederful.domain.task.dto.response; - -import java.util.List; -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class TasksResponse { - - private List content; - private Long totalElements; - private Long totalPages; - private Long size; - private Long number; -} From 3dc7483163f09821c2cbbb68a69b9c7e86574da5 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 11:31:01 +0900 Subject: [PATCH 107/123] =?UTF-8?q?refactor=20:=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=91=EB=8B=B5=20=EA=B0=9D=EC=B2=B4=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EA=B3=B5=ED=86=B5=20=ED=8F=B4=EB=8D=94=20=EC=A0=9C=EB=84=A4?= =?UTF-8?q?=EB=A6=AD=20=ED=81=B4=EB=9E=98=EC=8A=A4=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 --- .../domain/task/controller/TaskController.java | 4 ++-- .../domain/task/service/TaskService.java | 17 +++++++++-------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java index 6b9562f..2570a24 100644 --- a/src/main/java/com/example/onederful/domain/task/controller/TaskController.java +++ b/src/main/java/com/example/onederful/domain/task/controller/TaskController.java @@ -1,12 +1,12 @@ package com.example.onederful.domain.task.controller; import com.example.onederful.common.ApiResponseDto; +import com.example.onederful.common.ListResponse; import com.example.onederful.domain.task.common.CreateGroup; import com.example.onederful.domain.task.common.UpdateGroup; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; import com.example.onederful.domain.task.dto.request.TaskStatusUpdateRequest; import com.example.onederful.domain.task.dto.response.TaskResponse; -import com.example.onederful.domain.task.dto.response.TasksResponse; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.service.TaskService; import jakarta.servlet.http.HttpServletRequest; @@ -65,7 +65,7 @@ public ResponseEntity findTasks( ) { Pageable pageable = PageRequest.of(page, size, Direction.ASC, "dueDate"); - TasksResponse response = taskService.findTasks(pageable, search, status); + ListResponse response = taskService.findTasks(pageable, search, status); return ResponseEntity.ok(ApiResponseDto.success("업무 리스트 조회에 성공하였습니다.", response)); } diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index 0d8b239..de36493 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -1,9 +1,9 @@ package com.example.onederful.domain.task.service; +import com.example.onederful.common.ListResponse; import com.example.onederful.domain.task.dto.request.TaskSaveRequest; import com.example.onederful.domain.task.dto.request.TaskStatusUpdateRequest; import com.example.onederful.domain.task.dto.response.TaskResponse; -import com.example.onederful.domain.task.dto.response.TasksResponse; import com.example.onederful.domain.task.entity.Task; import com.example.onederful.domain.task.enums.ProcessStatus; import com.example.onederful.domain.task.repository.TaskRepository; @@ -63,16 +63,17 @@ public TaskResponse findTask(Long id) { } @Transactional(readOnly = true) - public TasksResponse findTasks(Pageable pageable, String search, ProcessStatus status) { + public ListResponse findTasks(Pageable pageable, String search, + ProcessStatus status) { Page tasks = taskRepository.findTasks(search, status, pageable); - return TasksResponse.builder() + return ListResponse.builder() .content(tasks.getContent().stream().map(TaskResponse::of).collect(Collectors.toList())) .totalElements(tasks.getTotalElements()) - .size((long) tasks.getSize()) - .number((long) tasks.getNumber()) - .totalPages((long) tasks.getTotalPages()) + .size(tasks.getSize()) + .number(tasks.getNumber()) + .totalPages(tasks.getTotalPages()) .build(); } @@ -128,14 +129,14 @@ private void taskUpdateValid(Task task, ProcessStatus status) { } if (task.getStatus() == ProcessStatus.TODO) { - if (status != ProcessStatus.IN_PROGRESS) { + if (status != ProcessStatus.TODO && status != ProcessStatus.IN_PROGRESS) { throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } task.taskStart(); } if (task.getStatus() == ProcessStatus.IN_PROGRESS) { - if (status != ProcessStatus.DONE) { + if (status != ProcessStatus.IN_PROGRESS && status != ProcessStatus.DONE) { throw new CustomException(ErrorCode.BAD_REQUEST_STATUS); } } From 02638f5749c208f141cc5e9a9d4ac36d4c3cffef Mon Sep 17 00:00:00 2001 From: doohaaa Date: Thu, 19 Jun 2025 13:59:49 +0900 Subject: [PATCH 108/123] =?UTF-8?q?refactor=20:=20=EB=8C=93=EA=B8=80=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=ED=98=95=EC=8B=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 24 +++------- .../comment/dto/CommentResponseDataDto.java | 32 ++++++++----- .../dto/CreateCommentResponseDataDto.java | 18 -------- .../domain/comment/dto/ResponseDto.java | 28 ------------ .../dto/UpdateCommentResponseDataDto.java | 25 ----------- .../domain/comment/dto/UserData.java | 27 +++++++++++ .../comment/service/CommentService.java | 45 +++++++------------ .../comment/service/CommentServiceTest.java | 10 ++--- 8 files changed, 76 insertions(+), 133 deletions(-) delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java delete mode 100644 src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java create mode 100644 src/main/java/com/example/onederful/domain/comment/dto/UserData.java diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 37cc60a..3a7e4e7 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -26,10 +26,10 @@ public class CommentController { @PostMapping("/tasks/{task_id}/comments") public ResponseEntity save(@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CommentRequestDto requestDto){ - CreateCommentResponseDataDto createCommentResponseDataDto = + CommentResponseDataDto CommentResponseDataDto = commentService.save(task_id, httpServletRequest, requestDto.getContent()); - ApiResponseDto success = ApiResponseDto.success("댓글이 생성되었습니다,", createCommentResponseDataDto); + ApiResponseDto success = ApiResponseDto.success("댓글이 생성되었습니다,", CommentResponseDataDto); return ResponseEntity.status(HttpStatus.OK).body(success); } @@ -40,28 +40,16 @@ public ResponseEntity updateComment( @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody CommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { - UpdateCommentResponseDataDto updateCommentResponseDataDto = + CommentResponseDataDto CommentResponseDataDto = commentService.updateComment(task_id, comment_id, requestDto.getContent(), httpServletRequest); - ApiResponseDto success = ApiResponseDto.success("댓글이 수정되었습니다.", updateCommentResponseDataDto); + ApiResponseDto success = ApiResponseDto.success("댓글이 수정되었습니다.", CommentResponseDataDto); return ResponseEntity.status(HttpStatus.OK).body(success); } - // 테스크별 댓글 조회 + // 댓글 조회 (테스크별) @GetMapping("/tasks/{task_id}/comments") - public ResponseEntity findAllCommentByTaskId( - @PathVariable Long task_id) { - - List commentResponseDataDtoList = commentService.findAllCommentByTaskId(task_id); - - ApiResponseDto success = ApiResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDataDtoList); - - return ResponseEntity.status(HttpStatus.OK).body(success); - } - - // 테스크별 댓글 조회 페이지화 - @GetMapping("/tasks/{task_id}/comments/pages") public ResponseEntity findAllCommentByTaskIdInPage( @PathVariable Long task_id, @RequestParam(defaultValue = "0") int page, @@ -75,7 +63,7 @@ public ResponseEntity findAllCommentByTaskIdInPage( return ResponseEntity.status(HttpStatus.OK).body(success); } - // 내용으로 댓글 조회 + // 댓글 조회 (내용 검색) @GetMapping("/search") public ResponseEntity findCommentByContent(@RequestBody CommentRequestDto requestDto) { diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java index 6833feb..1fe1076 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java @@ -1,33 +1,45 @@ package com.example.onederful.domain.comment.dto; import com.example.onederful.domain.comment.entity.Comment; +import lombok.AllArgsConstructor; +import lombok.Builder; import lombok.Getter; import java.time.LocalDate; import java.time.LocalDateTime; +@Builder +@AllArgsConstructor @Getter public class CommentResponseDataDto { - private final String writer; + private final Long id; private final String content; - private final Long comment_id; + private final Long taskId; + private final Long userId; + private final UserData userData; private final LocalDateTime createdAt; private final LocalDateTime updatedAt; - - public CommentResponseDataDto(Long comment_id, String writer, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { - this.comment_id = comment_id; - this.writer = writer; - this.content = content; - this.createdAt = createdAt; - this.updatedAt = updatedAt; + public static CommentResponseDataDto of(Comment comment){ + return CommentResponseDataDto.builder() + .id(comment.getId()) + .content(comment.getContent()) + .taskId(comment.getTask().getId()) + .userId(comment.getUser().getId()) + .userData(UserData.of(comment.getUser())) + .createdAt(comment.getCreatedAt()) + .updatedAt(comment.getUpdatedAt()) + .build(); } + public static CommentResponseDataDto from(Comment comment){ return new CommentResponseDataDto( comment.getId(), - comment.getUser().getName(), comment.getContent(), + comment.getTask().getId(), + comment.getUser().getId(), + UserData.of(comment.getUser()), comment.getCreatedAt(), comment.getUpdatedAt() ); diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java deleted file mode 100644 index e04c8e3..0000000 --- a/src/main/java/com/example/onederful/domain/comment/dto/CreateCommentResponseDataDto.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.example.onederful.domain.comment.dto; - -import lombok.Getter; - -@Getter -public class CreateCommentResponseDataDto { - - private final Long id; - private final String writer; - private final String content; - - public CreateCommentResponseDataDto(Long id, String writer, String content){ - this.id = id; - this.writer = writer; - this.content = content; - } - -} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java b/src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java deleted file mode 100644 index f9e81cc..0000000 --- a/src/main/java/com/example/onederful/domain/comment/dto/ResponseDto.java +++ /dev/null @@ -1,28 +0,0 @@ -package com.example.onederful.domain.comment.dto; - -import lombok.Getter; - -import java.time.OffsetDateTime; - -@Getter -public class ResponseDto { - private final boolean success; - private final String message; - private final T dataDto; - private final OffsetDateTime timestamp; - - public ResponseDto(boolean success, String message, T dataDto) { - this.success = success; - this.message = message; - this.dataDto = dataDto; - this.timestamp = OffsetDateTime.now(); - } - - public static ResponseDto success(String message, T data){ - return new ResponseDto<>(true, message, data); - } - - public static ResponseDto fail(String message){ - return new ResponseDto<>(false, message, null); - } -} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java deleted file mode 100644 index 9e49201..0000000 --- a/src/main/java/com/example/onederful/domain/comment/dto/UpdateCommentResponseDataDto.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.example.onederful.domain.comment.dto; - -import lombok.Getter; -import org.springframework.cglib.core.Local; - -import java.time.LocalDateTime; - -@Getter -public class UpdateCommentResponseDataDto { - - private final Long id; - private final String writer; - private final String content; - private final LocalDateTime created_at; - private final LocalDateTime updated_at; - - - public UpdateCommentResponseDataDto(Long id, String writer, String content, LocalDateTime createdAt, LocalDateTime updatedAt) { - this.id = id; - this.writer = writer; - this.content = content; - this.created_at = createdAt; - this.updated_at = updatedAt; - } -} diff --git a/src/main/java/com/example/onederful/domain/comment/dto/UserData.java b/src/main/java/com/example/onederful/domain/comment/dto/UserData.java new file mode 100644 index 0000000..8968bcf --- /dev/null +++ b/src/main/java/com/example/onederful/domain/comment/dto/UserData.java @@ -0,0 +1,27 @@ +package com.example.onederful.domain.comment.dto; + + +import com.example.onederful.domain.user.entity.User; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@Getter +@Builder +@AllArgsConstructor +public class UserData { + + private Long id; + private String username; + private String name; + private String email; + + public static UserData of(User user) { + return UserData.builder() + .id(user.getId()) + .username(user.getUsername()) + .name(user.getName()) + .email(user.getEmail()) + .build(); + } +} diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index d28c7c8..4bc59cc 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -1,9 +1,6 @@ package com.example.onederful.domain.comment.service; import com.example.onederful.domain.comment.dto.CommentResponseDataDto; -import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; -import com.example.onederful.domain.comment.dto.ResponseDto; -import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; import com.example.onederful.domain.task.entity.Task; @@ -32,7 +29,8 @@ public class CommentService { private final TaskRepository taskRepository; private final JwtUtil jwtUtil; - public CreateCommentResponseDataDto save(Long task_id, HttpServletRequest httpServletRequest, String content) { + // 댓글 생성 + public CommentResponseDataDto save(Long task_id, HttpServletRequest httpServletRequest, String content) { // 토큰에서 Id 가져오기 Long user_id = jwtUtil.extractId(httpServletRequest); @@ -44,19 +42,20 @@ public CreateCommentResponseDataDto save(Long task_id, HttpServletRequest httpSe .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); Comment comment = new Comment(content, user, task); - Comment savedComment = commentRepository.save(comment); - return new CreateCommentResponseDataDto(savedComment.getId(), user.getName(), savedComment.getContent()); + Comment savedComment = commentRepository.save(comment); + return CommentResponseDataDto.of(savedComment); } + // 댓글 수정 @Transactional - public UpdateCommentResponseDataDto updateComment(Long task_id, Long comment_id, String content, HttpServletRequest httpServletRequest) { + public CommentResponseDataDto updateComment(Long task_id, Long comment_id, String content, HttpServletRequest httpServletRequest) { Task task = taskRepository.findById(task_id) .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); Comment comment = commentRepository.findById(comment_id) - .orElseThrow(() ->new CustomException(ErrorCode.NONEXISTENT_COMMENT)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_COMMENT)); // 토큰에서 Id 가져오기 Long userId = jwtUtil.extractId(httpServletRequest); @@ -64,38 +63,27 @@ public UpdateCommentResponseDataDto updateComment(Long task_id, Long comment_id, User user = userRepository.findById(userId) .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); - if(comment.getIsDeleted()==true){ + if (comment.getIsDeleted() == true) { throw new CustomException(ErrorCode.INVALID_COMMENT); } comment.update(content); - return new UpdateCommentResponseDataDto(comment.getId(), user.getName(), comment.getContent(),comment.getCreatedAt(), comment.getUpdatedAt()); - } - - public List findAllCommentByTaskId(Long task_id){ - Task task = taskRepository.findById(task_id) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); - - List commentListById = commentRepository.findAllByTaskIdOrderByCreatedAtDesc(task_id); - - return commentListById.stream() - .filter(comment -> !comment.getIsDeleted()) - .map(CommentResponseDataDto::from) - .collect(Collectors.toList()); + return CommentResponseDataDto.of(comment); } - public Page findAllCommentByTaskIdInPage(Long task_id, Pageable pageable){ + // 댓글 조회 (테스크별) + public Page findAllCommentByTaskIdInPage(Long task_id, Pageable pageable) { // 페이징 대상 조회 final Page commentListByIdInPage = commentRepository.findByTaskIdAndIsDeletedFalse(task_id, pageable); return commentListByIdInPage.map(CommentResponseDataDto::from); } - - public List findCommentByContent(String content){ + // 댓글 조회 (내용 검색) + public List findCommentByContent(String content) { // 찾는 내용을 댓글을 적은 사람과 댓글 내용에서 검색 - List commentListByContent = commentRepository.findByContentOrUsername("%"+content+"%"); + List commentListByContent = commentRepository.findByContentOrUsername("%" + content + "%"); return commentListByContent.stream() .filter(comment -> !comment.getIsDeleted()) @@ -104,10 +92,11 @@ public List findCommentByContent(String content){ } + // 댓글 삭제 @Transactional - public void deleteComment(Long commentId){ + public void deleteComment(Long commentId) { Comment comment = commentRepository.findById(commentId) - .orElseThrow(() ->new CustomException(ErrorCode.NONEXISTENT_COMMENT)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_COMMENT)); comment.delete(); } diff --git a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java index 9d5ba8a..4d8b014 100644 --- a/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java +++ b/src/test/java/com/example/onederful/domain/comment/service/CommentServiceTest.java @@ -1,7 +1,6 @@ package com.example.onederful.domain.comment.service; -import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; -import com.example.onederful.domain.comment.dto.UpdateCommentResponseDataDto; +import com.example.onederful.domain.comment.dto.CommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; import com.example.onederful.domain.task.entity.Task; @@ -16,7 +15,6 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; -import org.springframework.http.HttpStatus; import java.time.LocalDateTime; import java.util.Optional; @@ -68,7 +66,7 @@ void save() { given(taskRepository.findById(task_id)).willReturn(Optional.of(task)); given(commentRepository.save(any(Comment.class))).willReturn(comment); // when - CreateCommentResponseDataDto result = commentService.save(task_id, httpServletRequest, content); + CommentResponseDataDto result = commentService.save(task_id, httpServletRequest, content); // then assertThat(result.getContent()).isEqualTo(content); @@ -103,11 +101,11 @@ void updateComment() { given(userRepository.findById(userId)).willReturn(Optional.of(user)); // when - UpdateCommentResponseDataDto result = commentService.updateComment(taskId, commentId, updatedContent, httpServletRequest); + CommentResponseDataDto result = commentService.updateComment(taskId, commentId, updatedContent, httpServletRequest); // then assertThat(result.getContent()).isEqualTo(updatedContent); - assertThat(result.getUpdated_at()).isNotNull(); + assertThat(result.getUpdatedAt()).isNotNull(); } From 5324df7b78c115c87c8fc3d6742cd2fb834c1322 Mon Sep 17 00:00:00 2001 From: doohaaa Date: Thu, 19 Jun 2025 18:00:10 +0900 Subject: [PATCH 109/123] =?UTF-8?q?fix=20:=20=EB=B3=80=EC=88=98=EB=AA=85?= =?UTF-8?q?=20=EC=9E=AC=EC=A7=80=EC=A0=95(=ED=94=84=EB=A1=A0=ED=8A=B8=20?= =?UTF-8?q?=EC=97=B0=EB=8F=99=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0),?= =?UTF-8?q?=20=EC=B6=9C=EB=A0=A5=20=EB=A9=94=EC=84=B8=EC=A7=80=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/controller/CommentController.java | 2 +- .../onederful/domain/comment/dto/CommentResponseDataDto.java | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 3a7e4e7..1b17cd2 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -58,7 +58,7 @@ public ResponseEntity findAllCommentByTaskIdInPage( Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); Page commentResponseDtoInPage = commentService.findAllCommentByTaskIdInPage(task_id,pageable); - ApiResponseDto success = ApiResponseDto.success("task " + task_id + "에 달린 댓글 목록", commentResponseDtoInPage); + ApiResponseDto success = ApiResponseDto.success("댓글 목록을 조회했습니다.", commentResponseDtoInPage); return ResponseEntity.status(HttpStatus.OK).body(success); } diff --git a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java index 1fe1076..5800071 100644 --- a/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java +++ b/src/main/java/com/example/onederful/domain/comment/dto/CommentResponseDataDto.java @@ -5,7 +5,6 @@ import lombok.Builder; import lombok.Getter; -import java.time.LocalDate; import java.time.LocalDateTime; @Builder @@ -16,7 +15,7 @@ public class CommentResponseDataDto { private final String content; private final Long taskId; private final Long userId; - private final UserData userData; + private final UserData user; private final LocalDateTime createdAt; private final LocalDateTime updatedAt; @@ -26,7 +25,7 @@ public static CommentResponseDataDto of(Comment comment){ .content(comment.getContent()) .taskId(comment.getTask().getId()) .userId(comment.getUser().getId()) - .userData(UserData.of(comment.getUser())) + .user(UserData.of(comment.getUser())) .createdAt(comment.getCreatedAt()) .updatedAt(comment.getUpdatedAt()) .build(); From 85f16017f1cf4605dbd06d66bfef6f763c804fc4 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 18:43:05 +0900 Subject: [PATCH 110/123] =?UTF-8?q?fix=20:=20=EC=9A=94=EA=B5=AC=EC=82=AC?= =?UTF-8?q?=ED=95=AD=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=83=9D?= =?UTF-8?q?=EC=84=B1=20/=20=EC=88=98=EC=A0=95=20=EC=9A=94=EC=B2=AD=20DTO?= =?UTF-8?q?=20=EB=A7=88=EA=B0=90=20=EC=8B=9C=EA=B0=84=20=ED=83=80=EC=9E=85?= =?UTF-8?q?=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/task/dto/request/TaskSaveRequest.java | 4 ++-- .../example/onederful/domain/task/service/TaskService.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java index 01e13b2..bd2cd07 100644 --- a/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java +++ b/src/main/java/com/example/onederful/domain/task/dto/request/TaskSaveRequest.java @@ -7,7 +7,7 @@ import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; -import java.time.OffsetDateTime; +import java.time.LocalDateTime; import lombok.Builder; import lombok.Getter; @@ -33,5 +33,5 @@ public class TaskSaveRequest { @NotNull(message = "마감일은 필수 항목입니다.") @FutureOrPresent(message = "마감일은 오늘이후만 가능합니다.") - private OffsetDateTime dueDate; + private LocalDateTime dueDate; } diff --git a/src/main/java/com/example/onederful/domain/task/service/TaskService.java b/src/main/java/com/example/onederful/domain/task/service/TaskService.java index de36493..bc7bbd8 100644 --- a/src/main/java/com/example/onederful/domain/task/service/TaskService.java +++ b/src/main/java/com/example/onederful/domain/task/service/TaskService.java @@ -45,7 +45,7 @@ public TaskResponse createTask(TaskSaveRequest request, HttpServletRequest httpS .assignee(manager) .user(me) .status(ProcessStatus.TODO) - .dueDate(request.getDueDate().toLocalDateTime()) + .dueDate(request.getDueDate()) .build(); Task savedTask = taskRepository.save(task); @@ -110,7 +110,7 @@ public TaskResponse updateTask(Long id, TaskSaveRequest request) { task.updateTask(request.getTitle(), request.getDescription(), request.getPriority(), assignee, - request.getDueDate().toLocalDateTime(), request.getStatus()); + request.getDueDate(), request.getStatus()); return TaskResponse.of(task); } From cfae0c100416f024db3c67b45e1340eb835c309a Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 19:43:14 +0900 Subject: [PATCH 111/123] =?UTF-8?q?refactor=20:=20Comment=20=ED=83=9C?= =?UTF-8?q?=EC=8A=A4=ED=81=AC=EB=B3=84=20=EB=8C=93=EA=B8=80=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=A1=B0=ED=9A=8C=20=EC=9D=91=EB=8B=B5=20=EA=B0=9D?= =?UTF-8?q?=EC=B2=B4=20=EC=88=98=EC=A0=95=20=EA=B3=B5=ED=86=B5=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EA=B0=9D=EC=B2=B4=20=EC=9E=AC=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../comment/controller/CommentController.java | 50 ++++++++++++------ .../comment/service/CommentService.java | 52 ++++++++++++------- 2 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 1b17cd2..8fc942f 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -1,19 +1,27 @@ package com.example.onederful.domain.comment.controller; import com.example.onederful.common.ApiResponseDto; -import com.example.onederful.domain.comment.dto.*; +import com.example.onederful.common.ListResponse; +import com.example.onederful.domain.comment.dto.CommentRequestDto; +import com.example.onederful.domain.comment.dto.CommentResponseDataDto; import com.example.onederful.domain.comment.service.CommentService; import jakarta.servlet.http.HttpServletRequest; +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.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.web.bind.annotation.*; - -import java.util.List; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +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; @RestController @RequestMapping("/api") @@ -24,10 +32,11 @@ public class CommentController { // 댓글 생성 @PostMapping("/tasks/{task_id}/comments") - public ResponseEntity save(@PathVariable Long task_id, HttpServletRequest httpServletRequest, @RequestBody CommentRequestDto requestDto){ + public ResponseEntity save(@PathVariable Long task_id, + HttpServletRequest httpServletRequest, @RequestBody CommentRequestDto requestDto) { CommentResponseDataDto CommentResponseDataDto = - commentService.save(task_id, httpServletRequest, requestDto.getContent()); + commentService.save(task_id, httpServletRequest, requestDto.getContent()); ApiResponseDto success = ApiResponseDto.success("댓글이 생성되었습니다,", CommentResponseDataDto); @@ -37,11 +46,13 @@ public ResponseEntity save(@PathVariable Long task_id, HttpServl // 댓글 수정 @PutMapping("/tasks/{task_id}/comments/{comment_id}") public ResponseEntity updateComment( - @PathVariable Long task_id, @PathVariable Long comment_id, @RequestBody CommentRequestDto requestDto, HttpServletRequest httpServletRequest + @PathVariable Long task_id, @PathVariable Long comment_id, + @RequestBody CommentRequestDto requestDto, HttpServletRequest httpServletRequest ) { CommentResponseDataDto CommentResponseDataDto = - commentService.updateComment(task_id, comment_id, requestDto.getContent(), httpServletRequest); + commentService.updateComment(task_id, comment_id, requestDto.getContent(), + httpServletRequest); ApiResponseDto success = ApiResponseDto.success("댓글이 수정되었습니다.", CommentResponseDataDto); @@ -51,12 +62,13 @@ public ResponseEntity updateComment( // 댓글 조회 (테스크별) @GetMapping("/tasks/{task_id}/comments") public ResponseEntity findAllCommentByTaskIdInPage( - @PathVariable Long task_id, - @RequestParam(defaultValue = "0") int page, - @RequestParam(defaultValue = "10") int size) { + @PathVariable Long task_id, + @RequestParam(defaultValue = "0") int page, + @RequestParam(defaultValue = "10") int size) { Pageable pageable = PageRequest.of(page, size, Sort.by(Sort.Direction.DESC, "createdAt")); - Page commentResponseDtoInPage = commentService.findAllCommentByTaskIdInPage(task_id,pageable); + ListResponse commentResponseDtoInPage = commentService.findAllCommentByTaskIdInPage( + task_id, pageable); ApiResponseDto success = ApiResponseDto.success("댓글 목록을 조회했습니다.", commentResponseDtoInPage); @@ -65,11 +77,14 @@ public ResponseEntity findAllCommentByTaskIdInPage( // 댓글 조회 (내용 검색) @GetMapping("/search") - public ResponseEntity findCommentByContent(@RequestBody CommentRequestDto requestDto) { + public ResponseEntity findCommentByContent( + @RequestBody CommentRequestDto requestDto) { - List commentResponseDataDtoList = commentService.findCommentByContent(requestDto.getContent()); + List commentResponseDataDtoList = commentService.findCommentByContent( + requestDto.getContent()); - ApiResponseDto success = ApiResponseDto.success(requestDto.getContent() + "가 포함된 댓글 목록 ", commentResponseDataDtoList); + ApiResponseDto success = ApiResponseDto.success(requestDto.getContent() + "가 포함된 댓글 목록 ", + commentResponseDataDtoList); return ResponseEntity.status(HttpStatus.OK).body(success); } @@ -77,7 +92,8 @@ public ResponseEntity findCommentByContent(@RequestBody CommentR // 댓글 삭제 @DeleteMapping("/tasks/{task_id}/comments/{comment_id}") - public ResponseEntity deleteComment(@PathVariable Long task_id, @PathVariable Long comment_id) { + public ResponseEntity deleteComment(@PathVariable Long task_id, + @PathVariable Long comment_id) { commentService.deleteComment(comment_id); diff --git a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java index 4bc59cc..b88b1e9 100644 --- a/src/main/java/com/example/onederful/domain/comment/service/CommentService.java +++ b/src/main/java/com/example/onederful/domain/comment/service/CommentService.java @@ -1,5 +1,6 @@ package com.example.onederful.domain.comment.service; +import com.example.onederful.common.ListResponse; import com.example.onederful.domain.comment.dto.CommentResponseDataDto; import com.example.onederful.domain.comment.entity.Comment; import com.example.onederful.domain.comment.repository.CommentRepository; @@ -11,15 +12,14 @@ import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.List; -import java.util.stream.Collectors; - @Service @RequiredArgsConstructor public class CommentService { @@ -30,16 +30,17 @@ public class CommentService { private final JwtUtil jwtUtil; // 댓글 생성 - public CommentResponseDataDto save(Long task_id, HttpServletRequest httpServletRequest, String content) { + public CommentResponseDataDto save(Long task_id, HttpServletRequest httpServletRequest, + String content) { // 토큰에서 Id 가져오기 Long user_id = jwtUtil.extractId(httpServletRequest); User user = userRepository.findById(user_id) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); Task task = taskRepository.findById(task_id) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); Comment comment = new Comment(content, user, task); @@ -50,20 +51,21 @@ public CommentResponseDataDto save(Long task_id, HttpServletRequest httpServletR // 댓글 수정 @Transactional - public CommentResponseDataDto updateComment(Long task_id, Long comment_id, String content, HttpServletRequest httpServletRequest) { + public CommentResponseDataDto updateComment(Long task_id, Long comment_id, String content, + HttpServletRequest httpServletRequest) { Task task = taskRepository.findById(task_id) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_TASK)); Comment comment = commentRepository.findById(comment_id) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_COMMENT)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_COMMENT)); // 토큰에서 Id 가져오기 Long userId = jwtUtil.extractId(httpServletRequest); User user = userRepository.findById(userId) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_USER)); - if (comment.getIsDeleted() == true) { + if (comment.getIsDeleted()) { throw new CustomException(ErrorCode.INVALID_COMMENT); } @@ -72,23 +74,33 @@ public CommentResponseDataDto updateComment(Long task_id, Long comment_id, Strin } // 댓글 조회 (테스크별) - public Page findAllCommentByTaskIdInPage(Long task_id, Pageable pageable) { + public ListResponse findAllCommentByTaskIdInPage(Long task_id, + Pageable pageable) { // 페이징 대상 조회 - final Page commentListByIdInPage = commentRepository.findByTaskIdAndIsDeletedFalse(task_id, pageable); - - return commentListByIdInPage.map(CommentResponseDataDto::from); + final Page commentListByIdInPage = commentRepository.findByTaskIdAndIsDeletedFalse( + task_id, pageable); + + return ListResponse.builder() + .content(commentListByIdInPage.getContent().stream().map(CommentResponseDataDto::of) + .collect(Collectors.toList())) + .size(commentListByIdInPage.getSize()) + .number(commentListByIdInPage.getNumber()) + .totalElements(commentListByIdInPage.getTotalElements()) + .totalPages(commentListByIdInPage.getTotalPages()) + .build(); } // 댓글 조회 (내용 검색) public List findCommentByContent(String content) { // 찾는 내용을 댓글을 적은 사람과 댓글 내용에서 검색 - List commentListByContent = commentRepository.findByContentOrUsername("%" + content + "%"); + List commentListByContent = commentRepository.findByContentOrUsername( + "%" + content + "%"); return commentListByContent.stream() - .filter(comment -> !comment.getIsDeleted()) - .map(CommentResponseDataDto::from) - .collect(Collectors.toList()); + .filter(comment -> !comment.getIsDeleted()) + .map(CommentResponseDataDto::from) + .collect(Collectors.toList()); } @@ -96,7 +108,7 @@ public List findCommentByContent(String content) { @Transactional public void deleteComment(Long commentId) { Comment comment = commentRepository.findById(commentId) - .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_COMMENT)); + .orElseThrow(() -> new CustomException(ErrorCode.NONEXISTENT_COMMENT)); comment.delete(); } From 405d2cd9735534b9b09c9d5293ce6885fccfb059 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 19:43:46 +0900 Subject: [PATCH 112/123] =?UTF-8?q?bug=20:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=20=EC=A4=91=20=EB=A1=9C=EA=B7=B8=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=97=90=EB=9F=AC=20=EB=B0=9C=EA=B2=AC=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/LoggingAspect.java | 180 +++++----- .../domain/log/service/LogService.java | 313 +++++++++--------- 2 files changed, 241 insertions(+), 252 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index fb9e713..174cc3e 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -1,8 +1,12 @@ package com.example.onederful.domain.log; +import com.example.onederful.domain.log.enums.Activity; +import com.example.onederful.domain.log.service.LogService; +import com.example.onederful.domain.task.entity.Task; +import com.example.onederful.domain.task.enums.ProcessStatus; +import com.example.onederful.domain.task.service.TaskService; import java.util.Objects; - -import org.aspectj.lang.JoinPoint; +import lombok.RequiredArgsConstructor; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.Around; @@ -10,97 +14,93 @@ import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; -import com.example.onederful.domain.log.enums.Activity; -import com.example.onederful.domain.log.service.LogService; -import com.example.onederful.domain.task.entity.Task; -import com.example.onederful.domain.task.enums.ProcessStatus; -import com.example.onederful.domain.task.service.TaskService; - -import lombok.RequiredArgsConstructor; - @Aspect @Component @RequiredArgsConstructor public class LoggingAspect { - private final HttpRequestUtil httpRequestUtil; - private final TaskService taskService; - private final LogService logService; - - @Pointcut("execution(* com.example..UserService.login(..))") - public void loginMethod() {} - - @Pointcut( - "execution(* com.example..TaskService.createTask(..)) || " + - "execution(* com.example..TaskService.updateTask(..)) || " + - "execution(* com.example..TaskService.deleteTask(..)) || " + - "execution(* com.example..CommentService.save(..)) || " + - "execution(* com.example..CommentService.updateComment(..)) || " + - "execution(* com.example..CommentService.deleteComment(..))" - ) - public void cudMethods() {} - - @Pointcut("execution(* com.example..TaskService.updateTaskStatus(..))") - public void updateTaskStatusMethod() {} - - // 로그인 시 자동 로그 기록 - @AfterReturning(pointcut = "loginMethod()", returning = "result") - public void logLoginMethod(Object result) { - - // HttpServletRequest으로부터 요청 ip, 메서드, url - HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); - - // 로그 저장 - logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); - } - - // 생성, 수정, 삭제 시 자동 로그 기록 - @AfterReturning(pointcut = "cudMethods()", returning = "result") - public void logCudMethods(Object result) { - - // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userid - HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); - - // 로그 저장 - logService.saveCudLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), result); - } - - // 상태 변경 시 자동 로그 기록 - @Around("updateTaskStatusMethod()") - public Object logTaskStatusChange(ProceedingJoinPoint joinPoint) throws Throwable { - Object[] args = joinPoint.getArgs(); - Long taskId = (Long) args[0]; // 첫 번째 인자가 taskId - - // 기존 task 상태 조회 - Task beforeTask = taskService.findById(taskId); // 서비스 계층 사용 - ProcessStatus beforeStatus = beforeTask != null ? beforeTask.getStatus() : null; - - // 메서드 실행 - Object result = joinPoint.proceed(); - - // 변경 후 task 상태 조회 - Task afterTask = taskService.findById(taskId); - ProcessStatus afterStatus = afterTask != null ? afterTask.getStatus() : null; - - // 변경되었는지 비교 후 로그 기록 - Activity activity = null; - if (Objects.equals(beforeStatus, ProcessStatus.TODO) && Objects.equals(afterStatus, ProcessStatus.IN_PROGRESS)) - { - activity = Activity.TASK_STATUS_TODO_TO_IN_PROGRESS; - } - else if (Objects.equals(beforeStatus, ProcessStatus.IN_PROGRESS) && Objects.equals(afterStatus, ProcessStatus.DONE)) - { - activity = Activity.TASK_STATUS_IN_PROGRESS_TO_DONE; - } - - if(activity != null) { - // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userid - HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); - - // 로그 저장 - logService.saveTaskStatusChangeLog(request.getIp(), request.getMethod(), request.getUrl(), request.getUserId(), taskId, activity); - } - - return result; - } + private final HttpRequestUtil httpRequestUtil; + private final TaskService taskService; + private final LogService logService; + + @Pointcut("execution(* com.example..UserService.login(..))") + public void loginMethod() { + } + + @Pointcut( + "execution(* com.example..TaskService.createTask(..)) || " + + "execution(* com.example..TaskService.updateTask(..)) || " + + "execution(* com.example..TaskService.deleteTask(..)) || " + + "execution(* com.example..CommentService.save(..)) || " + + "execution(* com.example..CommentService.updateComment(..)) || " + + "execution(* com.example..CommentService.deleteComment(..))" + ) + public void cudMethods() { + } + + @Pointcut("execution(* com.example..TaskService.updateTaskStatus(..))") + public void updateTaskStatusMethod() { + } + + // 로그인 시 자동 로그 기록 +// @AfterReturning(pointcut = "loginMethod()", returning = "result") +// public void logLoginMethod(Object result) { +// +// // HttpServletRequest으로부터 요청 ip, 메서드, url +// HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); +// +// // 로그 저장 +// logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); +// } + + // 생성, 수정, 삭제 시 자동 로그 기록 + @AfterReturning(pointcut = "cudMethods()", returning = "result") + public void logCudMethods(Object result) { + + // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userid + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + + // 로그 저장 + logService.saveCudLog(request.getIp(), request.getMethod(), request.getUrl(), + request.getUserId(), result); + } + + // 상태 변경 시 자동 로그 기록 + @Around("updateTaskStatusMethod()") + public Object logTaskStatusChange(ProceedingJoinPoint joinPoint) throws Throwable { + Object[] args = joinPoint.getArgs(); + Long taskId = (Long) args[0]; // 첫 번째 인자가 taskId + + // 기존 task 상태 조회 + Task beforeTask = taskService.findById(taskId); // 서비스 계층 사용 + ProcessStatus beforeStatus = beforeTask != null ? beforeTask.getStatus() : null; + + // 메서드 실행 + Object result = joinPoint.proceed(); + + // 변경 후 task 상태 조회 + Task afterTask = taskService.findById(taskId); + ProcessStatus afterStatus = afterTask != null ? afterTask.getStatus() : null; + + // 변경되었는지 비교 후 로그 기록 + Activity activity = null; + if (Objects.equals(beforeStatus, ProcessStatus.TODO) && Objects.equals(afterStatus, + ProcessStatus.IN_PROGRESS)) { + activity = Activity.TASK_STATUS_TODO_TO_IN_PROGRESS; + } else if (Objects.equals(beforeStatus, ProcessStatus.IN_PROGRESS) && Objects.equals( + afterStatus, ProcessStatus.DONE)) { + activity = Activity.TASK_STATUS_IN_PROGRESS_TO_DONE; + } + + if (activity != null) { + // HttpServletRequest으로부터 요청 ip, 메서드, url, 로그인한 userid + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + + // 로그 저장 + logService.saveTaskStatusChangeLog(request.getIp(), request.getMethod(), + request.getUrl(), request.getUserId(), taskId, activity); + } + + return result; + } } diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index d644ecf..669f869 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -1,14 +1,6 @@ package com.example.onederful.domain.log.service; -import java.time.LocalDate; -import java.util.stream.Collectors; - -import org.springframework.data.domain.Page; -import org.springframework.data.domain.Pageable; -import org.springframework.data.jpa.domain.Specification; -import org.springframework.stereotype.Service; - -import com.example.onederful.domain.comment.dto.CreateCommentResponseDataDto; +import com.example.onederful.domain.comment.dto.CommentResponseDataDto; import com.example.onederful.domain.log.dto.LogResponse; import com.example.onederful.domain.log.dto.LogsResponse; import com.example.onederful.domain.log.entity.Log; @@ -17,169 +9,166 @@ import com.example.onederful.domain.log.repository.LogRepository; import com.example.onederful.domain.log.repository.LogSpecification; import com.example.onederful.domain.task.dto.response.TaskResponse; -import com.example.onederful.domain.user.dto.Tokeninfo; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; import com.example.onederful.exception.CustomException; import com.example.onederful.exception.ErrorCode; import com.example.onederful.security.JwtUtil; - import jakarta.transaction.Transactional; +import java.time.LocalDate; +import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.domain.Specification; +import org.springframework.stereotype.Service; @Service @RequiredArgsConstructor public class LogService { - private final LogRepository logRepository; - private final UserRepository userRepositry; - private final JwtUtil jwtUtil; - - // log 조회 메서드 - public LogsResponse findLog( - Long userId, String activityStr, Long targetId, - LocalDate start, LocalDate end, Pageable pageable) { - - // 활동 유형 Enum 형태로 변환 - Activity activity = null; - try { - if (activityStr != null) { - activity = Activity.valueOf(activityStr); - } - } catch (IllegalArgumentException e) { - throw new CustomException(ErrorCode.INVALID_ACTIVITY); - } - - // 들어온 조건 여부로 동적 쿼리 설정 - Specification spec = - LogSpecification.hasUserId(userId) - .and(LogSpecification.hasActivity(activity)) - .and(LogSpecification.hasTargetId(targetId)) - .and(LogSpecification.betweenDates(start, end)); - - Page logs = logRepository.findAll(spec, pageable); - - return LogsResponse.builder() - .content(logs.getContent().stream().map(LogResponse::of).collect(Collectors.toList())) - .totalElements(logs.getTotalElements()) - .size((long) logs.getSize()) - .number((long) logs.getNumber()) - .totalPages((long) logs.getTotalPages()) - .build(); - } - - // 로그인 시 로그 기록 - @Transactional - public void saveLoginLog(String ip, Method method, String url, Object result) { - // userId - Long userId = null; - if (result instanceof Tokeninfo) { - String token = ((Tokeninfo) result).getToken(); - userId = jwtUtil.extractAllClaims(token).get("id", Long.class); - } - - // 현재 유저 조회 - User user = userRepositry.findById(userId).orElseThrow( - () -> new CustomException(ErrorCode.UNAUTHORIZED) - ); - - // 활동 유형 - Activity activity = Activity.USER_LOGGED_IN; - - // 대상 id - Long targetId = userId; - - // 로그 DB에 저장 - Log log = Log.builder() - .user(user) - .activity(activity) - .ipAddress(ip) - .method(method) - .targetId(targetId) - .requestUrl(url) - .build(); - - logRepository.save(log); - } - - // 생성, 수정, 삭제 시 로그 기록 - @Transactional - public void saveCudLog(String ip, Method method, String url, Long userId, Object result) { - // 현재 유저 조회 - User user = userRepositry.findById(userId).orElseThrow( - () -> new CustomException(ErrorCode.UNAUTHORIZED) - ); - - // 활동 유형 -> 요청 메서드와 url로 일치하는 활동 유형 찾기 - Activity activity = null; - if (method.equals(Method.POST) && url.contains("/comments")) { - activity = Activity.COMMENT_CREATED; - } - else if (method.equals(Method.PUT) && url.contains("/comments")) { - activity = Activity.COMMENT_UPDATED; - } - else if (method.equals(Method.DELETE) && url.contains("/comments")) { - activity = Activity.COMMENT_DELETED; - } - else if (method.equals(Method.POST) && url.contains("/tasks")) { - activity = Activity.TASK_CREATED; - } - else if (method.equals(Method.PUT) && url.contains("/tasks")) { - activity = Activity.TASK_UPDATED; - } - else if (method.equals(Method.DELETE) && url.contains("/tasks")) { - activity = Activity.TASK_DELETED; - } - - - // 대상 id -> 생성인 경우 응답에서 / 수정과 삭제의 경우 url 마지막에서 찾기 - Long targetId = null; - if (activity.equals(Activity.TASK_CREATED)) { - if (result instanceof TaskResponse) { - targetId = ((TaskResponse) result).getId(); - } - } - else if (activity.equals(Activity.COMMENT_CREATED)) { - if (result instanceof CreateCommentResponseDataDto) { - targetId = ((CreateCommentResponseDataDto) result).getId(); - } - } - else { - String[] parts = url.split("/"); - String lastPart = parts[parts.length - 1]; // /api/.../{id}의 id - targetId = Long.parseLong(lastPart); - } - - // 로그 DB에 저장 - Log log = Log.builder() - .user(user) - .activity(activity) - .ipAddress(ip) - .method(method) - .targetId(targetId) - .requestUrl(url) - .build(); - - logRepository.save(log); - } - - // 상태 변경 시 로그 기록 - public void saveTaskStatusChangeLog(String ip, Method method, String url, Long userId, Long targetId, Activity activity) { - // 현재 유저 조회 - User user = userRepositry.findById(userId).orElseThrow( - () -> new CustomException(ErrorCode.UNAUTHORIZED) - ); - - // 로그 DB에 저장 - Log log = Log.builder() - .user(user) - .activity(activity) - .ipAddress(ip) - .method(method) - .targetId(targetId) - .requestUrl(url) - .build(); - - logRepository.save(log); - } + private final LogRepository logRepository; + private final UserRepository userRepositry; + private final JwtUtil jwtUtil; + + // log 조회 메서드 + public LogsResponse findLog( + Long userId, String activityStr, Long targetId, + LocalDate start, LocalDate end, Pageable pageable) { + + // 활동 유형 Enum 형태로 변환 + Activity activity = null; + try { + if (activityStr != null) { + activity = Activity.valueOf(activityStr); + } + } catch (IllegalArgumentException e) { + throw new CustomException(ErrorCode.INVALID_ACTIVITY); + } + + // 들어온 조건 여부로 동적 쿼리 설정 + Specification spec = + LogSpecification.hasUserId(userId) + .and(LogSpecification.hasActivity(activity)) + .and(LogSpecification.hasTargetId(targetId)) + .and(LogSpecification.betweenDates(start, end)); + + Page logs = logRepository.findAll(spec, pageable); + + return LogsResponse.builder() + .content(logs.getContent().stream().map(LogResponse::of).collect(Collectors.toList())) + .totalElements(logs.getTotalElements()) + .size((long) logs.getSize()) + .number((long) logs.getNumber()) + .totalPages((long) logs.getTotalPages()) + .build(); + } + + // 로그인 시 로그 기록 +// @Transactional +// public void saveLoginLog(String ip, Method method, String url, Object result) { +// // userId +// Long userId = null; +// if (result instanceof Tokeninfo) { +// String token = ((Tokeninfo) result).getToken(); +// userId = jwtUtil.extractAllClaims(token).get("id", Long.class); +// } +// +// // 현재 유저 조회 +// User user = userRepositry.findById(userId).orElseThrow( +// () -> new CustomException(ErrorCode.UNAUTHORIZED) +// ); +// +// // 활동 유형 +// Activity activity = Activity.USER_LOGGED_IN; +// +// // 대상 id +// Long targetId = userId; +// +// // 로그 DB에 저장 +// Log log = Log.builder() +// .user(user) +// .activity(activity) +// .ipAddress(ip) +// .method(method) +// .targetId(targetId) +// .requestUrl(url) +// .build(); +// +// logRepository.save(log); +// } + + // 생성, 수정, 삭제 시 로그 기록 + @Transactional + public void saveCudLog(String ip, Method method, String url, Long userId, Object result) { + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + // 활동 유형 -> 요청 메서드와 url로 일치하는 활동 유형 찾기 + Activity activity = null; + if (method.equals(Method.POST) && url.contains("/comments")) { + activity = Activity.COMMENT_CREATED; + } else if (method.equals(Method.PUT) && url.contains("/comments")) { + activity = Activity.COMMENT_UPDATED; + } else if (method.equals(Method.DELETE) && url.contains("/comments")) { + activity = Activity.COMMENT_DELETED; + } else if (method.equals(Method.POST) && url.contains("/tasks")) { + activity = Activity.TASK_CREATED; + } else if (method.equals(Method.PUT) && url.contains("/tasks")) { + activity = Activity.TASK_UPDATED; + } else if (method.equals(Method.DELETE) && url.contains("/tasks")) { + activity = Activity.TASK_DELETED; + } + + // 대상 id -> 생성인 경우 응답에서 / 수정과 삭제의 경우 url 마지막에서 찾기 + Long targetId = null; + if (activity.equals(Activity.TASK_CREATED)) { + if (result instanceof TaskResponse) { + targetId = ((TaskResponse) result).getId(); + } + } else if (activity.equals(Activity.COMMENT_CREATED)) { + if (result instanceof CommentResponseDataDto) { + targetId = ((CommentResponseDataDto) result).getId(); + } + } else { + String[] parts = url.split("/"); + String lastPart = parts[parts.length - 1]; // /api/.../{id}의 id + targetId = Long.parseLong(lastPart); + } + + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } + + // 상태 변경 시 로그 기록 + public void saveTaskStatusChangeLog(String ip, Method method, String url, Long userId, + Long targetId, Activity activity) { + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } } From 496aaee29b90363b758632bb1200c78a857ae153 Mon Sep 17 00:00:00 2001 From: DongGeun Date: Thu, 19 Jun 2025 20:09:17 +0900 Subject: [PATCH 113/123] =?UTF-8?q?feat=20:=20README=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++- img.png | Bin 0 -> 771287 bytes 2 files changed, 156 insertions(+), 2 deletions(-) create mode 100644 img.png diff --git a/README.md b/README.md index ac72b89..661ab27 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,156 @@ -# spring-onederful -기업용 Task 관리 시스템입니다. +# 💫 아웃소싱 API + +
+ +## 🎀 프로젝트 소개 + +
+ +아웃소싱 형태로 진행된 백엔드 프로젝트입니다. + +클라이언트 측에서 프론트엔드 개발을 완료한 상태에 참여하였으며, + +REST API 기반으로 프론트엔드와 안정적으로 연동되는 백엔드 서버를 설계 및 구축하였습니다. + +요구사항 분석부터 API 설계, 예외처리까지 전바적인 서버 개발을 수행한 프로젝트입니다. + +> **내일배움캠프 1조** +> +> **개발기간 : 2025-06-13 ~ 2025-06-20** + +
+ +## 🧰 기술 스택 + +![Java17](https://img.shields.io/badge/Java17-red) +![Springboot3.5](https://img.shields.io/badge/Springboot3.5-yellow) +![JWT](https://img.shields.io/badge/JWT-orange) +![Spring Data JPA](https://img.shields.io/badge/Spring_Data_JPA-green) +![QueryDSL](https://img.shields.io/badge/QueryDSL-blue) +![MySQL](https://img.shields.io/badge/MySQL-purple) +![Swagger](https://img.shields.io/badge/Swagger-pink) + +
+ +## 🖼️ ERD + +![img.png](img.png) + +
+ +## 📜 API 명세서 + +API 명세서는 [OutSourcing Project API 문서](https://teamsparta.notion.site/API-2112dc3ef51480a9a21cf45c77d1e85f)를 클릭해주세요 + +
+ +## 👥 Team Member + +- **이의현 (팀장)** + 테스크 도메인 전반 (테스크 생성, 수정 ,조회, 상태변경, 삭제) 담당 + GitHub: [leeuihyun](https://github.com/leeuihyun) + + +- **이동근 (팀원)** + 회원 도메인 전반 (회원가입, 로그인, 유저 조회, JWT 인증) 담당 + GitHub: [DG0702](https://github.com/dg0702) + + +- **김두하 (팀원)** + 댓글 도메인 전반 (댓글 생성, 수정, 조회(검색), 삭제) 담당 + GitHub: [doohaaa](https://github.com/doohaaa) + + +- **김민성 (팀원)** + 대시보드 도메인 전반 (통계 정보 제공, 내 테스크 요약) 담당 + GitHub: [urzn](https://github.com/urzn) + + +- **우새빛 (팀원)** + 활동로그 도메인 전반 (주요 활동 기록, 활동 로그 조회) 담당 + GitHub: [saevit](https://github.com/saevit) + +
+ +## ✨ 주요 기능 + +- **docker를 이용하여 프론트엔드와 연결** + + +- **프론트엔드, 백엔드의 연결 → 연동 검증 : 브라우저에서 실제 요청/응답 확인** + +
+ +## 🪄 트러블 슈팅 + +### USER 도메인 + +- **406 Error (회원가입, 로그인)** + + - **응답 할 때 OffsetDateTime 역직렬화 불가 → 의존성을 추가하여 해결** + + +- **JWT 예외처리** + + - **`@ControllerAdvice`를 이용한 JWT 예외를 원하는 응답 형태로 변경 → Controller 보다 먼저 실행 되어 수동으로 응답 형태 생성** + + +- **CORS** + + - **docker 이용하여 프론트엔드 연결 후 백엔드 로직 실행 → CORS 문제 발생하여 CORS 설정하여 해결** + +### TASK 도메인 + +- **DB 정규화 지키기 위한 과도한 설계** + + - **불필요하게 테이블의 복잡성 상승 → Enum을 사용하여 불필요한 분리를 줄이고 타입의 안정성 상승** + + +- **TestCode** + + - **테스트 코드 작성하여 Sturbing 후 실행하였지만 값을 반환하지 않음** + + - **반환값을 직접 지정하여 해결** + +### COMMNET 도메인 + +- **협업의 어려움** + + - **각 도메인 파트별로 개발 → 나중에 연관이 있는 부분을 공통적으로 통일해야하는 문제 발생** + + - **팀원과 소통하며 기본적인 틀에서 조금씩 수정하여 해결** + + +- **프론트엔드 API를 이용한 개발의 어려움** + + - **API 설계를 도메인 위주로 하였으나 프론트 엔드 API와 달라 기능이 구현되지 않음** + + - **프론트엔드 API에 맞추어 API를 일부 수정하여 해결** + +### DASHBOARD + +- **Priority task 정렬** + + - **Priority`(Enum)` high-medium-low로 정렬하기 위해 `Enum`에 정수 필드를 추가 방식과 `Map<>`을 사용하여 정렬하는 방식을 고민** + + - **`Map<>`을 사용하는것으로 결정 → 순서를 정렬하는 로직이 이 경우밖에 없어서 결정** + + - **추가적으로 순서를 정렬하는 로직이 있을 경우 `Enum`에 정수 필드를 추가하여 사용하는 방향으로 선택** + +### LOG + +- **AOP 도입 및 책임 분리의 어려움** + + - **로직 분리의 기준을 정하는데 어려움 → 공통 처리와 비즈니스 로직 사이의 경계가 모호** + + - **AOP → 요청 메서드, URL, 로그인 한 유저ID 공통 정보 추출** + + - **추출한 데이터를 서비스 계층으로 전달하여 가공 및 DB 저장을 담당하도록 구조 설계함** + + + + + + + + diff --git a/img.png b/img.png new file mode 100644 index 0000000000000000000000000000000000000000..18e47816a1c84ad8d0bf6ca908b7ba58f0771236 GIT binary patch literal 771287 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ð{75wz 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
  • d4ySexzPn7Yz3aPOf9Qp*X79I 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

    1;nGt7cCJI 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

    o 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

    qYBADS#$q?VYxBPxMoe>{`G0UA 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Μ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�qPPwBU~(730d_}spr?x~ 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 M>Kg0RXgS9I58l|tQ~&?~ literal 0 HcmV?d00001 From edbc5dfc64c4e4b7828404a5a2b5f56c84670c8b Mon Sep 17 00:00:00 2001 From: DongGeun Date: Thu, 19 Jun 2025 20:26:28 +0900 Subject: [PATCH 114/123] =?UTF-8?q?refactor=20:=20=EC=86=8C=EB=AC=B8?= =?UTF-8?q?=EC=9E=90=20=EB=8C=80=EB=AC=B8=EC=9E=90=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 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 661ab27..b60f0ed 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ API 명세서는 [OutSourcing Project API 문서](https://teamsparta.notion.site ### USER 도메인 -- **406 Error (회원가입, 로그인)** +- **406 ERROR (회원가입, 로그인)** - **응답 할 때 OffsetDateTime 역직렬화 불가 → 의존성을 추가하여 해결** From 00405120a5ff8d0c3e561a52d8788ded4a0134e6 Mon Sep 17 00:00:00 2001 From: saevit Date: Thu, 19 Jun 2025 20:43:55 +0900 Subject: [PATCH 115/123] =?UTF-8?q?fix:=20=EB=A1=9C=EA=B7=B8=EC=9D=B8?= =?UTF-8?q?=EA=B3=BC=20=ED=9A=8C=EC=9B=90=EA=B0=80=EC=9E=85=EC=8B=9C=20Htt?= =?UTF-8?q?pRequestUtil=EC=97=90=EC=84=9C=20=ED=86=A0=ED=81=B0=EC=9D=84=20?= =?UTF-8?q?=ED=86=B5=ED=95=9C=20userId=20=EA=B0=80=EC=A0=B8=EC=98=A4?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/example/onederful/domain/log/HttpRequestUtil.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java index 1c955a2..8d6ce5c 100644 --- a/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java +++ b/src/main/java/com/example/onederful/domain/log/HttpRequestUtil.java @@ -42,7 +42,11 @@ public RequestInfo getRequestInfo() { String url = request.getRequestURI(); // 토큰으로부터 요청한 사용자의 userId - Long userId = jwtUtil.extractId(request); + Long userId = null; + // 로그인, 회원가입 등 토큰 체크 안 할 URL 처리 + if (!url.startsWith("/api/auth/login") && !url.startsWith("/api/auth/register")) { + userId = jwtUtil.extractId(request); + } return new RequestInfo(ip, enumMethod, url, userId); } From 9360093828ed213484fdb8880b366e835e1d4c73 Mon Sep 17 00:00:00 2001 From: saevit Date: Thu, 19 Jun 2025 20:57:43 +0900 Subject: [PATCH 116/123] =?UTF-8?q?fix:=20=EC=98=A4=EB=A5=98=EB=A1=9C=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=B2=98=EB=A6=AC=20=ED=96=88=EB=8D=98=20?= =?UTF-8?q?=EB=B6=80=EB=B6=84=20=ED=95=B4=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/log/LoggingAspect.java | 18 ++--- .../domain/log/service/LogService.java | 65 ++++++++++--------- 2 files changed, 42 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java index 174cc3e..ff92320 100644 --- a/src/main/java/com/example/onederful/domain/log/LoggingAspect.java +++ b/src/main/java/com/example/onederful/domain/log/LoggingAspect.java @@ -43,15 +43,15 @@ public void updateTaskStatusMethod() { } // 로그인 시 자동 로그 기록 -// @AfterReturning(pointcut = "loginMethod()", returning = "result") -// public void logLoginMethod(Object result) { -// -// // HttpServletRequest으로부터 요청 ip, 메서드, url -// HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); -// -// // 로그 저장 -// logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); -// } + @AfterReturning(pointcut = "loginMethod()", returning = "result") + public void logLoginMethod(Object result) { + + // HttpServletRequest으로부터 요청 ip, 메서드, url + HttpRequestUtil.RequestInfo request = httpRequestUtil.getRequestInfo(); + + // 로그 저장 + logService.saveLoginLog(request.getIp(), request.getMethod(), request.getUrl(), result); + } // 생성, 수정, 삭제 시 자동 로그 기록 @AfterReturning(pointcut = "cudMethods()", returning = "result") diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index 669f869..bf23d26 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -9,6 +9,7 @@ import com.example.onederful.domain.log.repository.LogRepository; import com.example.onederful.domain.log.repository.LogSpecification; import com.example.onederful.domain.task.dto.response.TaskResponse; +import com.example.onederful.domain.user.dto.Tokeninfo; import com.example.onederful.domain.user.entity.User; import com.example.onederful.domain.user.repository.UserRepository; import com.example.onederful.exception.CustomException; @@ -65,38 +66,38 @@ public LogsResponse findLog( } // 로그인 시 로그 기록 -// @Transactional -// public void saveLoginLog(String ip, Method method, String url, Object result) { -// // userId -// Long userId = null; -// if (result instanceof Tokeninfo) { -// String token = ((Tokeninfo) result).getToken(); -// userId = jwtUtil.extractAllClaims(token).get("id", Long.class); -// } -// -// // 현재 유저 조회 -// User user = userRepositry.findById(userId).orElseThrow( -// () -> new CustomException(ErrorCode.UNAUTHORIZED) -// ); -// -// // 활동 유형 -// Activity activity = Activity.USER_LOGGED_IN; -// -// // 대상 id -// Long targetId = userId; -// -// // 로그 DB에 저장 -// Log log = Log.builder() -// .user(user) -// .activity(activity) -// .ipAddress(ip) -// .method(method) -// .targetId(targetId) -// .requestUrl(url) -// .build(); -// -// logRepository.save(log); -// } + @Transactional + public void saveLoginLog(String ip, Method method, String url, Object result) { + // userId + Long userId = null; + if (result instanceof Tokeninfo) { + String token = ((Tokeninfo) result).getToken(); + userId = jwtUtil.extractAllClaims(token).get("id", Long.class); + } + + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + // 활동 유형 + Activity activity = Activity.USER_LOGGED_IN; + + // 대상 id + Long targetId = userId; + + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } // 생성, 수정, 삭제 시 로그 기록 @Transactional From 52b13a2df95691055073b2d23cbbd07c0f49560a Mon Sep 17 00:00:00 2001 From: kimminsung Date: Thu, 19 Jun 2025 21:30:05 +0900 Subject: [PATCH 117/123] =?UTF-8?q?fix:=20Dashboard=20Repository=20Test=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=96=B4=EB=85=B8=ED=85=8C=EC=9D=B4?= =?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 --- .../domain/dashboard/repository/DashboardRepositoryTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java b/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java index dc9a031..866e670 100644 --- a/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java +++ b/src/test/java/com/example/onederful/domain/dashboard/repository/DashboardRepositoryTest.java @@ -12,6 +12,7 @@ import jakarta.transaction.Transactional; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.ActiveProfiles; import java.util.List; @@ -22,7 +23,7 @@ import java.time.LocalDateTime; -@SpringBootTest +@DataJpaTest @ActiveProfiles("test") @Transactional public class DashboardRepositoryTest { @@ -124,6 +125,8 @@ public class DashboardRepositoryTest { .dueDate(LocalDateTime.now().plusDays(5)) .build() ); + em.flush(); + em.clear(); //when StatisticsResponseDto result = dashboardRepository.getStatistics(); From d61a3ee2c572fe404229a37280bd6a417eb30247 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 21:43:50 +0900 Subject: [PATCH 118/123] =?UTF-8?q?fix=20:=20API=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B3=80=EA=B2=BD=EC=9C=BC=EB=A1=9C=20?= =?UTF-8?q?=EC=9D=B8=ED=95=9C=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94?= =?UTF-8?q?=EB=93=9C=20=EC=88=98=EC=A0=95=20=EB=B9=84=EC=A6=88=EB=8B=88?= =?UTF-8?q?=EC=8A=A4=20=EB=A1=9C=EC=A7=81=20=EC=88=98=EC=A0=95=20=ED=9B=84?= =?UTF-8?q?=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EC=BD=94=EB=93=9C=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=ED=95=98=EC=A7=80=20=EC=95=8A=EC=9D=80=20=EB=B6=80?= =?UTF-8?q?=EB=B6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../onederful/domain/task/service/TaskServiceTest.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java index 7a822aa..9ed2995 100644 --- a/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java +++ b/src/test/java/com/example/onederful/domain/task/service/TaskServiceTest.java @@ -17,7 +17,6 @@ import com.example.onederful.security.JwtUtil; import jakarta.servlet.http.HttpServletRequest; import java.time.LocalDateTime; -import java.time.OffsetDateTime; import java.util.List; import java.util.Optional; import org.junit.jupiter.api.Assertions; @@ -58,7 +57,7 @@ public class TaskServiceTest { .description("description") .priority(Priority.LOW) .assigneeId(1L) - .dueDate(OffsetDateTime.parse("2027-04-02T23:59:59Z")) + .dueDate(LocalDateTime.of(2027, 4, 2, 23, 59, 59)) .build(); HttpServletRequest httpServletRequest = new MockHttpServletRequest(); @@ -91,7 +90,7 @@ public class TaskServiceTest { .assignee(manager) .user(me) .status(ProcessStatus.TODO) - .dueDate(request.getDueDate().toLocalDateTime()) + .dueDate(request.getDueDate()) .build(); ReflectionTestUtils.setField(task, "createdAt", LocalDateTime.now()); @@ -298,7 +297,7 @@ public class TaskServiceTest { .priority(Priority.LOW) .assigneeId(1L) .status(ProcessStatus.IN_PROGRESS) - .dueDate(OffsetDateTime.parse("2027-04-02T23:59:59Z")) + .dueDate(LocalDateTime.of(2027, 4, 2, 23, 59, 59)) .build(); Long userId = 1L; From 1ac35062fc711f8402ca674c69102eb93d6fbf79 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 21:44:35 +0900 Subject: [PATCH 119/123] =?UTF-8?q?fix=20:=20API=20=EC=9A=94=EA=B5=AC?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EC=9E=98=EB=AA=BB=20=EC=9E=91=EC=84=B1?= =?UTF-8?q?=EB=90=98=EC=96=B4=EC=9E=88=EB=8A=94=20=EB=B6=80=EB=B6=84=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20API=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD?= =?UTF-8?q?=EC=9D=80=20taskId=EA=B0=80=20=EC=9E=88=EC=A7=80=EB=A7=8C=20?= =?UTF-8?q?=EC=8B=A4=EC=A0=9C=20=EB=84=A4=ED=8A=B8=EC=9B=8C=ED=81=AC=20?= =?UTF-8?q?=EC=9A=94=EC=B2=AD=EC=9D=80=20=EC=97=86=EC=9D=8C=20=EB=84=A4?= =?UTF-8?q?=ED=8A=B8=EC=9B=8C=ED=81=AC=20=EC=9A=94=EC=B2=AD=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=20=EB=B3=80=EA=B2=BD=ED=95=98=EC=97=AC=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/comment/controller/CommentController.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java index 8fc942f..c2551f4 100644 --- a/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java +++ b/src/main/java/com/example/onederful/domain/comment/controller/CommentController.java @@ -91,8 +91,8 @@ public ResponseEntity findCommentByContent( // 댓글 삭제 - @DeleteMapping("/tasks/{task_id}/comments/{comment_id}") - public ResponseEntity deleteComment(@PathVariable Long task_id, + @DeleteMapping("/comments/{comment_id}") + public ResponseEntity deleteComment( @PathVariable Long comment_id) { commentService.deleteComment(comment_id); From 546050729ae2db818834cc78534f864cdce07c36 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Thu, 19 Jun 2025 21:50:15 +0900 Subject: [PATCH 120/123] =?UTF-8?q?refactor=20:=20Pagination=20=EC=9E=AC?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=20=ED=81=B4=EB=9E=98=EC=8A=A4=20DTO=EB=A1=9C?= =?UTF-8?q?=20=ED=86=B5=ED=95=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/log/controller/LogController.java | 70 ++++++++--------- .../domain/log/dto/LogsResponse.java | 17 ----- .../domain/log/service/LogService.java | 76 +++++++++---------- 3 files changed, 73 insertions(+), 90 deletions(-) delete mode 100644 src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java diff --git a/src/main/java/com/example/onederful/domain/log/controller/LogController.java b/src/main/java/com/example/onederful/domain/log/controller/LogController.java index 76bf437..4ff49a3 100644 --- a/src/main/java/com/example/onederful/domain/log/controller/LogController.java +++ b/src/main/java/com/example/onederful/domain/log/controller/LogController.java @@ -1,7 +1,11 @@ package com.example.onederful.domain.log.controller; +import com.example.onederful.common.ApiResponseDto; +import com.example.onederful.common.ListResponse; +import com.example.onederful.domain.log.dto.LogResponse; +import com.example.onederful.domain.log.service.LogService; import java.time.LocalDate; - +import lombok.RequiredArgsConstructor; import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Sort; import org.springframework.data.web.PageableDefault; @@ -11,42 +15,38 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import com.example.onederful.common.ApiResponseDto; -import com.example.onederful.domain.log.dto.LogsResponse; -import com.example.onederful.domain.log.service.LogService; - -import lombok.RequiredArgsConstructor; - @RestController @RequiredArgsConstructor public class LogController { - private final LogService logService; - - /** - * 활동 로그 조회 - * - * 검색 조건: - * @param userId 유저 아이디 (필수 N) - * @param activity 활동 유형 (필수 N) - * @param targetId 대상 ID (필수 N) - * @param start 시작일 (필수 N) - * @param end 종료일 (필수 N) - * @param pageable 페이징을 위한 page, size, sort (필수 N) - * @return 조회된 활동 로그 - */ - @GetMapping("/api/activities") - public ResponseEntity getLog( - @RequestParam(required = false) Long userId, - @RequestParam(required = false) String activity, - @RequestParam(required = false) Long targetId, - @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start, - @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end, - @PageableDefault(page = 0, size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable - ) { - - LogsResponse response = logService.findLog(userId, activity, targetId, start, end, pageable); - - return ResponseEntity.ok(ApiResponseDto.success("활동 로그 리스트 조회에 성공하였습니다.", response)); - } + private final LogService logService; + + /** + * 활동 로그 조회 + *

    + * 검색 조건: + * + * @param userId 유저 아이디 (필수 N) + * @param activity 활동 유형 (필수 N) + * @param targetId 대상 ID (필수 N) + * @param start 시작일 (필수 N) + * @param end 종료일 (필수 N) + * @param pageable 페이징을 위한 page, size, sort (필수 N) + * @return 조회된 활동 로그 + */ + @GetMapping("/api/activities") + public ResponseEntity getLog( + @RequestParam(required = false) Long userId, + @RequestParam(required = false) String activity, + @RequestParam(required = false) Long targetId, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate start, + @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end, + @PageableDefault(page = 0, size = 10, sort = "createdAt", direction = Sort.Direction.DESC) Pageable pageable + ) { + + ListResponse response = logService.findLog(userId, activity, targetId, start, + end, pageable); + + return ResponseEntity.ok(ApiResponseDto.success("활동 로그 리스트 조회에 성공하였습니다.", response)); + } } diff --git a/src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java b/src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java deleted file mode 100644 index fc74102..0000000 --- a/src/main/java/com/example/onederful/domain/log/dto/LogsResponse.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.example.onederful.domain.log.dto; - -import java.util.List; - -import lombok.Builder; -import lombok.Getter; - -@Getter -@Builder -public class LogsResponse { - - private List content; - private Long totalElements; - private Long totalPages; - private Long size; - private Long number; -} diff --git a/src/main/java/com/example/onederful/domain/log/service/LogService.java b/src/main/java/com/example/onederful/domain/log/service/LogService.java index bf23d26..df2ce0b 100644 --- a/src/main/java/com/example/onederful/domain/log/service/LogService.java +++ b/src/main/java/com/example/onederful/domain/log/service/LogService.java @@ -1,8 +1,8 @@ package com.example.onederful.domain.log.service; +import com.example.onederful.common.ListResponse; import com.example.onederful.domain.comment.dto.CommentResponseDataDto; import com.example.onederful.domain.log.dto.LogResponse; -import com.example.onederful.domain.log.dto.LogsResponse; import com.example.onederful.domain.log.entity.Log; import com.example.onederful.domain.log.enums.Activity; import com.example.onederful.domain.log.enums.Method; @@ -33,7 +33,7 @@ public class LogService { private final JwtUtil jwtUtil; // log 조회 메서드 - public LogsResponse findLog( + public ListResponse findLog( Long userId, String activityStr, Long targetId, LocalDate start, LocalDate end, Pageable pageable) { @@ -56,48 +56,48 @@ public LogsResponse findLog( Page logs = logRepository.findAll(spec, pageable); - return LogsResponse.builder() + return ListResponse.builder() .content(logs.getContent().stream().map(LogResponse::of).collect(Collectors.toList())) .totalElements(logs.getTotalElements()) - .size((long) logs.getSize()) - .number((long) logs.getNumber()) - .totalPages((long) logs.getTotalPages()) + .size(logs.getSize()) + .number(logs.getNumber()) + .totalPages(logs.getTotalPages()) .build(); } // 로그인 시 로그 기록 - @Transactional - public void saveLoginLog(String ip, Method method, String url, Object result) { - // userId - Long userId = null; - if (result instanceof Tokeninfo) { - String token = ((Tokeninfo) result).getToken(); - userId = jwtUtil.extractAllClaims(token).get("id", Long.class); - } - - // 현재 유저 조회 - User user = userRepositry.findById(userId).orElseThrow( - () -> new CustomException(ErrorCode.UNAUTHORIZED) - ); - - // 활동 유형 - Activity activity = Activity.USER_LOGGED_IN; - - // 대상 id - Long targetId = userId; - - // 로그 DB에 저장 - Log log = Log.builder() - .user(user) - .activity(activity) - .ipAddress(ip) - .method(method) - .targetId(targetId) - .requestUrl(url) - .build(); - - logRepository.save(log); - } + @Transactional + public void saveLoginLog(String ip, Method method, String url, Object result) { + // userId + Long userId = null; + if (result instanceof Tokeninfo) { + String token = ((Tokeninfo) result).getToken(); + userId = jwtUtil.extractAllClaims(token).get("id", Long.class); + } + + // 현재 유저 조회 + User user = userRepositry.findById(userId).orElseThrow( + () -> new CustomException(ErrorCode.UNAUTHORIZED) + ); + + // 활동 유형 + Activity activity = Activity.USER_LOGGED_IN; + + // 대상 id + Long targetId = userId; + + // 로그 DB에 저장 + Log log = Log.builder() + .user(user) + .activity(activity) + .ipAddress(ip) + .method(method) + .targetId(targetId) + .requestUrl(url) + .build(); + + logRepository.save(log); + } // 생성, 수정, 삭제 시 로그 기록 @Transactional From 850273cfcd52ff4b7b360d30e6b5a8a38781be1f Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 20 Jun 2025 10:59:17 +0900 Subject: [PATCH 121/123] =?UTF-8?q?feat=20:=20driver-class-name=20?= =?UTF-8?q?=EC=86=8D=EC=84=B1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/application.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index e8f7b4e..ec9fc33 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -6,9 +6,10 @@ spring: url: ${DB_URL} username: ${DB_USERNAME} password: ${DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver jwt: secret: key: ${SECRET_KEY} - expiration : 3600000 \ No newline at end of file + expiration: 3600000 \ No newline at end of file From cb5e2b65f6a83526beff2ebd248353bbcb7abb5b Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 20 Jun 2025 11:17:07 +0900 Subject: [PATCH 122/123] =?UTF-8?q?docs=20:=20README=20=EC=98=A4=ED=83=80?= =?UTF-8?q?=20=EC=88=98=EC=A0=95=20/=20=EC=9A=B4=EC=98=81=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20=EB=B3=80=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 61 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index b60f0ed..10db19b 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,16 @@


    -아웃소싱 형태로 진행된 백엔드 프로젝트입니다. +아웃소싱 형태로 진행된 백엔드 프로젝트입니다. 클라이언트 측에서 프론트엔드 개발을 완료한 상태에 참여하였으며, REST API 기반으로 프론트엔드와 안정적으로 연동되는 백엔드 서버를 설계 및 구축하였습니다. -요구사항 분석부터 API 설계, 예외처리까지 전바적인 서버 개발을 수행한 프로젝트입니다. +요구사항 분석부터 API 설계, 예외처리까지 전반적인 서버 개발을 수행한 프로젝트입니다. > **내일배움캠프 1조** -> +> > **개발기간 : 2025-06-13 ~ 2025-06-20**
    @@ -38,13 +38,15 @@ REST API 기반으로 프론트엔드와 안정적으로 연동되는 백엔드
    -## 📜 API 명세서 +## 📜 API 명세서 -API 명세서는 [OutSourcing Project API 문서](https://teamsparta.notion.site/API-2112dc3ef51480a9a21cf45c77d1e85f)를 클릭해주세요 +API +명세서는 [OutSourcing Project API 문서](https://teamsparta.notion.site/API-2112dc3ef51480a9a21cf45c77d1e85f) +를 클릭해주세요
    -## 👥 Team Member +## 👥 Team Member - **이의현 (팀장)** 테스크 도메인 전반 (테스크 생성, 수정 ,조회, 상태변경, 삭제) 담당 @@ -81,71 +83,82 @@ API 명세서는 [OutSourcing Project API 문서](https://teamsparta.notion.site
    +## ✨운영 환경 변수 + +```json +DB_URL=jdbc:mysql: //localhost:3306/yourdb +DB_USERNAME=yourusername +DB_PASSWORD=youruserpassword +SECRET_KEY=your_jwt_secret_key +``` + +
    + ## 🪄 트러블 슈팅 -### USER 도메인 +### USER 도메인 - **406 ERROR (회원가입, 로그인)** - - **응답 할 때 OffsetDateTime 역직렬화 불가 → 의존성을 추가하여 해결** + - **응답 할 때 OffsetDateTime 역직렬화 불가 → 의존성을 추가하여 해결** - **JWT 예외처리** - - **`@ControllerAdvice`를 이용한 JWT 예외를 원하는 응답 형태로 변경 → Controller 보다 먼저 실행 되어 수동으로 응답 형태 생성** + - **`@ControllerAdvice`를 이용한 JWT 예외를 원하는 응답 형태로 변경 → Controller 보다 먼저 실행 되어 수동으로 응답 형태 생성** - **CORS** - - **docker 이용하여 프론트엔드 연결 후 백엔드 로직 실행 → CORS 문제 발생하여 CORS 설정하여 해결** + - **docker 이용하여 프론트엔드 연결 후 백엔드 로직 실행 → CORS 문제 발생하여 CORS 설정하여 해결** ### TASK 도메인 - **DB 정규화 지키기 위한 과도한 설계** - - **불필요하게 테이블의 복잡성 상승 → Enum을 사용하여 불필요한 분리를 줄이고 타입의 안정성 상승** + - **불필요하게 테이블의 복잡성 상승 → Enum을 사용하여 불필요한 분리를 줄이고 타입의 안정성 상승** - **TestCode** - - **테스트 코드 작성하여 Sturbing 후 실행하였지만 값을 반환하지 않음** + - **테스트 코드 작성하여 Sturbing 후 실행하였지만 값을 반환하지 않음** - - **반환값을 직접 지정하여 해결** + - **반환값을 직접 지정하여 해결** ### COMMNET 도메인 - **협업의 어려움** - - **각 도메인 파트별로 개발 → 나중에 연관이 있는 부분을 공통적으로 통일해야하는 문제 발생** + - **각 도메인 파트별로 개발 → 나중에 연관이 있는 부분을 공통적으로 통일해야하는 문제 발생** - - **팀원과 소통하며 기본적인 틀에서 조금씩 수정하여 해결** + - **팀원과 소통하며 기본적인 틀에서 조금씩 수정하여 해결** - **프론트엔드 API를 이용한 개발의 어려움** - - **API 설계를 도메인 위주로 하였으나 프론트 엔드 API와 달라 기능이 구현되지 않음** + - **API 설계를 도메인 위주로 하였으나 프론트 엔드 API와 달라 기능이 구현되지 않음** - - **프론트엔드 API에 맞추어 API를 일부 수정하여 해결** + - **프론트엔드 API에 맞추어 API를 일부 수정하여 해결** ### DASHBOARD - **Priority task 정렬** - - - **Priority`(Enum)` high-medium-low로 정렬하기 위해 `Enum`에 정수 필드를 추가 방식과 `Map<>`을 사용하여 정렬하는 방식을 고민** - - **`Map<>`을 사용하는것으로 결정 → 순서를 정렬하는 로직이 이 경우밖에 없어서 결정** + - **Priority`(Enum)` high-medium-low로 정렬하기 위해 `Enum`에 정수 필드를 추가 방식과 `Map<>`을 사용하여 정렬하는 방식을 고민** + + - **`Map<>`을 사용하는것으로 결정 → 순서를 정렬하는 로직이 이 경우밖에 없어서 결정** - - **추가적으로 순서를 정렬하는 로직이 있을 경우 `Enum`에 정수 필드를 추가하여 사용하는 방향으로 선택** + - **추가적으로 순서를 정렬하는 로직이 있을 경우 `Enum`에 정수 필드를 추가하여 사용하는 방향으로 선택** ### LOG - **AOP 도입 및 책임 분리의 어려움** - - **로직 분리의 기준을 정하는데 어려움 → 공통 처리와 비즈니스 로직 사이의 경계가 모호** + - **로직 분리의 기준을 정하는데 어려움 → 공통 처리와 비즈니스 로직 사이의 경계가 모호** - - **AOP → 요청 메서드, URL, 로그인 한 유저ID 공통 정보 추출** + - **AOP → 요청 메서드, URL, 로그인 한 유저ID 공통 정보 추출** - - **추출한 데이터를 서비스 계층으로 전달하여 가공 및 DB 저장을 담당하도록 구조 설계함** + - **추출한 데이터를 서비스 계층으로 전달하여 가공 및 DB 저장을 담당하도록 구조 설계함** From d21d05459149ef1191fa15b418a4f0f4ccb951d8 Mon Sep 17 00:00:00 2001 From: leeuihyun Date: Fri, 20 Jun 2025 11:33:58 +0900 Subject: [PATCH 123/123] =?UTF-8?q?docs=20:=20README=20sql=20=EC=8B=A4?= =?UTF-8?q?=ED=96=89=20=EB=B0=A9=EB=B2=95=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 10db19b..38a008b 100644 --- a/README.md +++ b/README.md @@ -94,6 +94,14 @@ SECRET_KEY=your_jwt_secret_key
    +## ✨SQL 실행방법 + +- 데이터베이스 자동생성 X +- `onederful.sql` 을 본인 데이터베이스에서 실행시켜서 수동 적용합니다. +- `onederful.sql` 은 최상위 경로에 있습니다. + +
    + ## 🪄 트러블 슈팅 ### USER 도메인
  • 184RD=B(qbnP~CPLOQT*1 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