From e0da9eeae1a911a1b2c12eb9e8ec62e826a228f4 Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 17:02:19 +0900 Subject: [PATCH 01/10] =?UTF-8?q?fix(service):=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20url=20=EC=88=98=EC=A0=95=20|?= =?UTF-8?q?=20DP-171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deepwebide_be/member/service/EmailVerificationService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java b/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java index 9ab8961d..ba83e44a 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java @@ -40,7 +40,7 @@ public String createVerification(String email) { // 이메일 인증 요청 메일 발송 public void sendVerificationEmail(String email, String code) { // String link = "http://localhost:8080/api/auth/email/send-code?code=" + code; - String link = "https://api.deepwebide.site/api/auth/email/send-code?code=" + code; + String link = "https://api.deepdirect.site/api/auth/email/send-code?code=" + code; SimpleMailMessage message = new SimpleMailMessage(); message.setTo(email); From 1a9b1e91842e881b07ddf9793a036370cfb71cf6 Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 17:17:08 +0900 Subject: [PATCH 02/10] =?UTF-8?q?fix(util):=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=20=ED=98=95=EC=9A=A9=EC=82=AC=20=EC=B6=94=EA=B0=80=20|=20DP-17?= =?UTF-8?q?1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/util/NicknameGenerator.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java b/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java index ea13853d..e66b2512 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java @@ -6,11 +6,15 @@ public class NicknameGenerator { private static final List ADJECTIVES = List.of( - "슬기로운", "권태로운", "우는", "웃는", "기쁜", "화난", "차가운", "뜨거운", "평범한", "용감한", "행복한", - "느긋한", "조용한", "시끄러운", "상냥한", "무뚝뚝한", "겁쟁이인", "귀여운", "엉뚱한", "멍한", "똑똑한", "배고픈", - "침착한", "우울한", "광기어린", "수줍은", "분노한", "우아한", "애매한", "날카로운", "귀찮은", "엉망진창인", - "반짝이는", "무서운", "요란한", "재빠른", "정중한", "자신감 넘치는", "불안한", "느린", "심심한", "정신없는", - "끈질긴", "달콤한", "과묵한", "산만한", "진지한", "까칠한", "활기찬", "졸린", "자유로운", "호기심 많은", "고통스러운" + "겁쟁이인", "고상한", "고통스러운", "과묵한", "광기어린", "괴상한", "권태로운", "귀여운", "귀찮은", "기쁜", + "까칠한", "깨끗한", "끈질긴", "날카로운", "노련한", "느긋한", "느린", "달콤한", "따뜻한", "똑똑한", + "뜨거운", "멍한", "무뚝뚝한", "무서운", "반짝이는", "밝은", "배고픈", "부끄러운", "분노한", "불안한", + "빠른", "산만한", "상냥한", "상쾌한", "서투른", "수줍은", "쉬운", "슬기로운", "시끄러운", "신난", + "심란한", "심심한", "쓸쓸한", "애매한", "어두운", "어려운", "엉뚱한", "엉망진창인", "엉큼한", "여유로운", + "예민한", "요란한", "요망한", "용감한", "우는", "우아한", "우울한", "웃는", "의젓한", "자신감넘치는", + "자유로운", "작은", "장난스런", "재빠른", "정신없는", "정중한", "조급한", "조용한", "졸린", "즐거운", + "진지한", "차가운", "침착한", "큰", "평범한", "피곤한", "행복한", "호기심 많은", "화난", "활기찬", + "활발한", "흥분한", "희망찬" ); private static final Random RANDOM = new Random(); From 18828c396125a49ad2c89105e7e292d132074b91 Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 17:19:46 +0900 Subject: [PATCH 03/10] =?UTF-8?q?fix(util):=20=EB=8B=89=EB=84=A4=EC=9E=84?= =?UTF-8?q?=20=ED=98=95=EC=9A=A9=EC=82=AC=20=EC=B6=94=EA=B0=80=20|=20DP-17?= =?UTF-8?q?1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deepwebide_be/member/util/NicknameGenerator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java b/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java index e66b2512..38a352f4 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/util/NicknameGenerator.java @@ -13,8 +13,8 @@ public class NicknameGenerator { "심란한", "심심한", "쓸쓸한", "애매한", "어두운", "어려운", "엉뚱한", "엉망진창인", "엉큼한", "여유로운", "예민한", "요란한", "요망한", "용감한", "우는", "우아한", "우울한", "웃는", "의젓한", "자신감넘치는", "자유로운", "작은", "장난스런", "재빠른", "정신없는", "정중한", "조급한", "조용한", "졸린", "즐거운", - "진지한", "차가운", "침착한", "큰", "평범한", "피곤한", "행복한", "호기심 많은", "화난", "활기찬", - "활발한", "흥분한", "희망찬" + "진지한", "차가운", "침착한", "큰", "평범한", "피곤한", "행복한", "호기심 많은", "홀가분한", "화난", + "활기찬", "활발한", "흥분한", "희망찬" ); private static final Random RANDOM = new Random(); From cf9bc87c4c71cb819485cc4bbcd35b8fb257c391 Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 18:42:24 +0900 Subject: [PATCH 04/10] =?UTF-8?q?fix(controller):=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EB=A7=81=ED=81=AC=20=ED=81=B4?= =?UTF-8?q?=EB=A6=AD=20=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=EB=A1=9C=20=EB=A6=AC=EB=8B=A4=EC=9D=B4?= =?UTF-8?q?=EB=A0=89=ED=8A=B8=20|=20DP-171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../EmailVerificationController.java | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java b/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java index 3ff6a404..787ce4bf 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java @@ -7,18 +7,8 @@ import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.view.RedirectView; -import java.util.HashMap; -import java.util.Map; - -//@CrossOrigin( -// origins = { -// "http://localhost:5173", -// "https://www.deepdirect.site", -// "https://api.deepdirect.site" -// }, -// allowCredentials = "true" -//) @RestController @RequiredArgsConstructor @RequestMapping("/api/auth/email") @@ -31,19 +21,11 @@ public class EmailVerificationController { summary = "이메일 인증" ) @GetMapping("/send-code") - public ResponseEntity> verifyEmail(@RequestParam String code) { - boolean result = emailVerificationService.verifyEmailCode(code); - Map response = new HashMap<>(); + public RedirectView verifyEmail(@RequestParam String code) { + emailVerificationService.verifyEmailCode(code); - // TODO: 리다이랙트 넣기~ - if (result) { - response.put("success", true); - response.put("message", "이메일 인증이 완료되었습니다."); - return ResponseEntity.ok(response); - } else { - response.put("success", false); - response.put("message", "인증 코드가 만료되었거나 유효하지 않습니다."); - return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(response); - } + RedirectView redirectView = new RedirectView(); + redirectView.setUrl("https://www.deepdirect.site/sign-in"); + return redirectView; } } From b782fcfd5067c70d41ad99465964297ccbb8306a Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 18:42:56 +0900 Subject: [PATCH 05/10] =?UTF-8?q?fix(service):=20=EA=B8=B0=EC=A1=B4=20?= =?UTF-8?q?=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=20=ED=99=95=EC=9D=B8=20=EC=BD=94=EB=93=9C=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20|=20DP-171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deepwebide_be/member/service/EmailVerificationService.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java b/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java index ba83e44a..15234a15 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java @@ -53,7 +53,6 @@ public void sendVerificationEmail(String email, String code) { // 이메일 인증 코드 검증 public boolean verifyEmailCode(String code) { return emailVerificationRepository.findByEmailCode(code) - .filter(verification -> !verification.isVerified()) // 기존 인증 여부 확인 .filter(verification -> verification.getExpiresAt().isAfter(LocalDateTime.now())) // 만료 여부 확인 .map(verification -> { From 3610fdf2a75ec130a124f1f4c5508b39c33485ef Mon Sep 17 00:00:00 2001 From: vayaconchoi Date: Thu, 31 Jul 2025 18:46:11 +0900 Subject: [PATCH 06/10] =?UTF-8?q?fix(=EC=BD=94=EB=93=9C=EC=B0=B8=EC=A1=B0?= =?UTF-8?q?=20=EA=B2=BD=EB=A1=9C=20=EC=A1=B0=ED=9A=8C=EC=8B=9C=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=EB=A7=8C=20=EC=A1=B0=ED=9A=8C):=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EC=B0=B8=EC=A1=B0=20=EA=B2=BD=EB=A1=9C=20=EC=A1=B0=ED=9A=8C?= =?UTF-8?q?=EC=8B=9C=20=ED=8C=8C=EC=9D=BC=EB=A7=8C=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?DP-172?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 코드 참조 경로 조회시 파일만 조회 - FileType을 보고 FILE인 것만 조회되도록 수정 --- .../chat/service/ChatMessageService.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/chat/service/ChatMessageService.java b/src/main/java/com/deepdirect/deepwebide_be/chat/service/ChatMessageService.java index b913f057..8c6ebd46 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/chat/service/ChatMessageService.java +++ b/src/main/java/com/deepdirect/deepwebide_be/chat/service/ChatMessageService.java @@ -10,6 +10,7 @@ import com.deepdirect.deepwebide_be.chat.repository.ChatMessageReferenceRepository; import com.deepdirect.deepwebide_be.chat.repository.ChatMessageRepository; import com.deepdirect.deepwebide_be.file.domain.FileNode; +import com.deepdirect.deepwebide_be.file.domain.FileType; import com.deepdirect.deepwebide_be.file.repository.FileNodeRepository; import com.deepdirect.deepwebide_be.global.exception.ErrorCode; import com.deepdirect.deepwebide_be.global.exception.GlobalException; @@ -164,15 +165,9 @@ public CodePathListResponse getCodePaths(Long repositoryId, Long userId) { List fileNodes = fileNodeRepository.findAllByRepositoryId(repositoryId); List paths = fileNodes.stream() + .filter(node -> node.getFileType() == FileType.FILE) // ← 폴더는 제외 .map(FileNode::getPath) - .sorted((a, b) -> { - // 폴더 먼저, 사전순 정렬 - boolean isAFolder = a.endsWith("/"); - boolean isBFolder = b.endsWith("/"); - if (isAFolder && !isBFolder) return -1; - if (!isAFolder && isBFolder) return 1; - return a.compareToIgnoreCase(b); - }) + .sorted(String::compareToIgnoreCase) .toList(); return CodePathListResponse.builder().paths(paths).build(); From 1bb92faa7cfab4e91088fe1f222addbd47051e10 Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 19:02:06 +0900 Subject: [PATCH 07/10] =?UTF-8?q?fix(controller):=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=9B=84=20=EC=9D=B8=EC=A6=9D=20=EC=97=AC=EB=B6=80=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=20UserService=EC=97=90=20mail=20=EC=A0=84?= =?UTF-8?q?=EB=8B=AC=20|=20DP-171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/controller/EmailVerificationController.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java b/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java index 787ce4bf..a8b8ad6a 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/controller/EmailVerificationController.java @@ -1,6 +1,7 @@ package com.deepdirect.deepwebide_be.member.controller; import com.deepdirect.deepwebide_be.member.service.EmailVerificationService; +import com.deepdirect.deepwebide_be.member.service.UserService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -16,13 +17,19 @@ public class EmailVerificationController { private final EmailVerificationService emailVerificationService; + private final UserService userService; @Operation( summary = "이메일 인증" ) @GetMapping("/send-code") public RedirectView verifyEmail(@RequestParam String code) { - emailVerificationService.verifyEmailCode(code); + boolean result = emailVerificationService.verifyEmailCode(code); + String email = emailVerificationService.findVerifiedEmailByCode(code); + + if (result) { + userService.setEmailVerificationService(email); + } RedirectView redirectView = new RedirectView(); redirectView.setUrl("https://www.deepdirect.site/sign-in"); From f22bb1ba2faa76013643d78b0931a8f4442571af Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 19:02:52 +0900 Subject: [PATCH 08/10] =?UTF-8?q?fix(servie):=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=A1=B0=ED=9A=8C=20?= =?UTF-8?q?=ED=9B=84=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EB=B0=98=ED=99=98=20?= =?UTF-8?q?|=20DP-171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/service/EmailVerificationService.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java b/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java index 15234a15..84ed3791 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/service/EmailVerificationService.java @@ -63,4 +63,10 @@ public boolean verifyEmailCode(String code) { }) .orElse(false); } + + public String findVerifiedEmailByCode(String code) { + return emailVerificationRepository.findByEmailCode(code) + .map(EmailVerification::getEmail) + .orElseThrow(() -> new IllegalArgumentException("해당 코드로 등록된 이메일이 없습니다.")); + } } From 7e363998338e4b86342b524edb944a82f47db976 Mon Sep 17 00:00:00 2001 From: Shin-Yu-1 Date: Thu, 31 Jul 2025 19:03:28 +0900 Subject: [PATCH 09/10] =?UTF-8?q?fix(servie):=20=EC=A0=84=EB=8B=AC?= =?UTF-8?q?=EB=B0=9B=EC=9D=80=20=EC=9D=B4=EB=A9=94=EC=9D=BC=EC=9D=98=20?= =?UTF-8?q?=EC=9D=B8=EC=A6=9D=EC=97=AC=EB=B6=80=20true=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20|=20DP-171?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../deepwebide_be/member/service/UserService.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/com/deepdirect/deepwebide_be/member/service/UserService.java b/src/main/java/com/deepdirect/deepwebide_be/member/service/UserService.java index 9dad9720..cbf14c42 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/member/service/UserService.java +++ b/src/main/java/com/deepdirect/deepwebide_be/member/service/UserService.java @@ -266,4 +266,13 @@ public void verifyAndResetPassword(PasswordResetRequest request, String authoriz userRepository.save(user); reauthTokenService.delete(email); } + + @Transactional + public void setEmailVerificationService(String email) { + User user = userRepository.findByEmail(email) + .orElseThrow(() -> new GlobalException(ErrorCode.USER_NOT_FOUND)); + + user.setEmailVerified(true); + userRepository.save(user); + } } From 098975a8c15404b88738601de1bdd081730818c3 Mon Sep 17 00:00:00 2001 From: projectmiluju Date: Thu, 31 Jul 2025 19:16:53 +0900 Subject: [PATCH 10/10] =?UTF-8?q?feat(history):=20=ED=9E=88=EC=8A=A4?= =?UTF-8?q?=ED=86=A0=EB=A6=AC=20=EC=A0=80=EC=9E=A5=20=EB=A1=9C=EC=A7=81=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20DP-169?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../repository/FileContentRepository.java | 5 + .../dto/request/HistorySaveRequest.java | 29 ---- .../history/service/HistoryService.java | 131 +++++------------- 3 files changed, 39 insertions(+), 126 deletions(-) diff --git a/src/main/java/com/deepdirect/deepwebide_be/file/repository/FileContentRepository.java b/src/main/java/com/deepdirect/deepwebide_be/file/repository/FileContentRepository.java index 85ada5f4..f983711a 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/file/repository/FileContentRepository.java +++ b/src/main/java/com/deepdirect/deepwebide_be/file/repository/FileContentRepository.java @@ -3,7 +3,10 @@ import com.deepdirect.deepwebide_be.file.domain.FileContent; import com.deepdirect.deepwebide_be.file.domain.FileNode; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; +import java.util.List; import java.util.Optional; public interface FileContentRepository extends JpaRepository { @@ -12,4 +15,6 @@ public interface FileContentRepository extends JpaRepository Optional findByFileNode(FileNode fileNode); + @Query("SELECT fc FROM FileContent fc WHERE fc.fileNode.repository.id = :repositoryId") + List findAllByRepositoryId(@Param("repositoryId") Long repositoryId); } diff --git a/src/main/java/com/deepdirect/deepwebide_be/history/dto/request/HistorySaveRequest.java b/src/main/java/com/deepdirect/deepwebide_be/history/dto/request/HistorySaveRequest.java index 65449a6d..28060d3b 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/history/dto/request/HistorySaveRequest.java +++ b/src/main/java/com/deepdirect/deepwebide_be/history/dto/request/HistorySaveRequest.java @@ -14,33 +14,4 @@ public class HistorySaveRequest { @Schema(description = "저장 메시지(커밋 메시지)", example = "1차 개발 완료") private String message; - @Schema(description = "저장할 파일/폴더 노드 목록 (트리 구조 아님, 전체 파일/폴더의 납작한 배열)") - private List nodes; - - @Getter - @NoArgsConstructor - @Schema(description = "파일 또는 폴더 노드 정보") - public static class NodeDto { - - @Schema(description = "파일/폴더 ID (생성 직후는 null일 수 있음, 기존 파일은 PK)", - example = "4") - private Long fileId; - - @Schema(description = "파일/폴더명", example = "Main.java") - private String fileName; - - @Schema(description = "노드 타입 (FILE: 파일, FOLDER: 폴더)", example = "FILE") - private String fileType; - - @Schema(description = "부모 폴더 ID (최상위면 null)", example = "1") - private Long parentId; - - @Schema(description = "파일/폴더 전체 경로", example = "src/Main.java") - private String path; - - @Schema(description = "파일 내용 (파일일 때만 존재, 폴더면 null)", - example = "public class Main { ... }", - nullable = true) - private String content; - } } diff --git a/src/main/java/com/deepdirect/deepwebide_be/history/service/HistoryService.java b/src/main/java/com/deepdirect/deepwebide_be/history/service/HistoryService.java index ab2df92c..6eb7b4a4 100644 --- a/src/main/java/com/deepdirect/deepwebide_be/history/service/HistoryService.java +++ b/src/main/java/com/deepdirect/deepwebide_be/history/service/HistoryService.java @@ -45,74 +45,48 @@ public class HistoryService { @Transactional public HistorySaveResponse saveHistory(Long repositoryId, Long userId, HistorySaveRequest request) { - - for (HistorySaveRequest.NodeDto dto : request.getNodes()) { - System.out.println( - "fileId=" + dto.getFileId() + - ", fileName=" + dto.getFileName() + - ", parentId=" + dto.getParentId() + - ", path=" + dto.getPath() - ); - } - // 1. 권한 체크 및 레포 조회 Repository repo = repositoryRepository.findByIdAndMemberOrOwner(repositoryId, userId) .orElseThrow(() -> new GlobalException(ErrorCode.REPOSITORY_NOT_FOUND)); - // 2. 요청에서 전체 fileId set 추출 - Set requestFileIds = request.getNodes().stream() - .map(HistorySaveRequest.NodeDto::getFileId) - .collect(Collectors.toSet()); - - // 3. 현재 DB에 있는 FileNode 전체 조회 (삭제 대상 판별용) + // 2. 현재 DB의 파일/폴더 전체 조회 List dbNodes = fileNodeRepository.findAllByRepositoryId(repositoryId); - // 4. DB에 있지만 요청에 없는 FileNode 삭제 (자식 먼저 삭제) - List toDelete = dbNodes.stream() - .filter(node -> !requestFileIds.contains(node.getId())) - .sorted((a, b) -> b.getPath().length() - a.getPath().length()) - .toList(); - for (FileNode node : toDelete) { - if (node.getFileType() == FileType.FILE) { - fileContentRepository.deleteByFileNode(node); - } - fileNodeRepository.delete(node); - } - - // 5. id → FileNode (DB에 이미 있던 것만) - Map idToNode = dbNodes.stream() - .collect(Collectors.toMap(FileNode::getId, n -> n)); - - // 6. id → 요청 NodeDto - Map idToDto = request.getNodes().stream() - .collect(Collectors.toMap(HistorySaveRequest.NodeDto::getFileId, n -> n)); - - // 7. parent → 자식 순서로 재귀 저장 - for (Long nodeId : idToDto.keySet()) { - saveNodeRecursive(nodeId, idToNode, idToDto, repo); - } - - // 8. History & HistoryFile 기록 (스냅샷처럼) - History history = History.builder() - .repository(repo) - .message(request.getMessage()) - .authorId(userId) - .createdAt(LocalDateTime.now()) - .build(); - history = historyRepository.save(history); - - History finalHistory = history; - List historyFiles = request.getNodes().stream() - .map(dto -> HistoryFile.builder() - .history(finalHistory) - .fileId(dto.getFileId()) - .fileName(dto.getFileName()) - .fileType(dto.getFileType()) - .parentId(dto.getParentId()) - .path(dto.getPath()) - .content(dto.getContent()) + // 3. 파일 내용도 모두 조회 (FileContent와 Join, 또는 fileContentRepository 사용) + Map nodeIdToContent = fileContentRepository.findAllByRepositoryId(repositoryId) + .stream().collect(Collectors.toMap( + c -> c.getFileNode().getId(), c -> c + )); + + // 4. History 생성 + History history = historyRepository.save( + History.builder() + .repository(repo) + .message(request.getMessage()) + .authorId(userId) + .createdAt(LocalDateTime.now()) + .build() + ); + + // 5. HistoryFile (스냅샷) 기록 + List historyFiles = dbNodes.stream() + .map(node -> HistoryFile.builder() + .history(history) + .fileId(node.getId()) + .fileName(node.getName()) + .fileType(node.getFileType().name()) + .parentId(node.getParent() != null ? node.getParent().getId() : null) + .path(node.getPath()) + .content( + node.getFileType() == FileType.FILE + ? (nodeIdToContent.get(node.getId()) != null + ? new String(nodeIdToContent.get(node.getId()).getContent(), StandardCharsets.UTF_8) + : null) + : null + ) .build() ).toList(); + historyFileRepository.saveAll(historyFiles); return HistorySaveResponse.builder() @@ -120,43 +94,6 @@ public HistorySaveResponse saveHistory(Long repositoryId, Long userId, HistorySa .build(); } - private void saveNodeRecursive( - Long clientFileId, - Map idToNode, - Map idToDto, - Repository repo - ) { - // 이미 저장된 노드는 무시 - if (idToNode.containsKey(clientFileId)) return; - - HistorySaveRequest.NodeDto dto = idToDto.get(clientFileId); - - FileNode parent = null; - if (dto.getParentId() != null) { - saveNodeRecursive(dto.getParentId(), idToNode, idToDto, repo); - parent = idToNode.get(dto.getParentId()); - } - - FileNode fileNode = FileNode.builder() - .repository(repo) - .name(dto.getFileName()) - .fileType(FileType.valueOf(dto.getFileType())) - .parent(parent) - .path(dto.getPath()) - .build(); - fileNode = fileNodeRepository.save(fileNode); - - idToNode.put(clientFileId, fileNode); - - if (fileNode.getFileType() == FileType.FILE) { - FileContent content = FileContent.builder() - .fileNode(fileNode) - .content(dto.getContent() == null ? new byte[0] : dto.getContent().getBytes(StandardCharsets.UTF_8)) - .build(); - fileContentRepository.save(content); - } - } - @Transactional(readOnly = true) public HistoryDetailResponse getHistoryDetail(Long repositoryId, Long historyId, Long userId) { // 1. 권한 체크 & 레포 확인