From b0720bcb75606fc82d42c89bd67325336f262a5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 17:57:27 +0900 Subject: [PATCH 01/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=BB=A8=ED=8A=B8=EB=A1=A4=EB=9F=AC=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 qwerqwer --- .../mail/controller/MailController.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/main/java/land/leets/domain/mail/controller/MailController.java b/src/main/java/land/leets/domain/mail/controller/MailController.java index fcbbaab..bb4e158 100644 --- a/src/main/java/land/leets/domain/mail/controller/MailController.java +++ b/src/main/java/land/leets/domain/mail/controller/MailController.java @@ -1,6 +1,9 @@ package land.leets.domain.mail.controller; +import land.leets.domain.mail.controller.dto.RecruitMailRequest; +import land.leets.domain.mail.usecase.SubscribeRecruitMail; 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; @@ -19,6 +22,7 @@ public class MailController { private final SendMailCron sendMailCron; + private final SubscribeRecruitMail subscribeRecruitMail; @Operation(summary = "서류 결과 메일 전송", description = "서류 지원 결과를 메일로 전송합니다.") @ApiResponses({ @@ -47,4 +51,32 @@ public boolean sendFinalMail() { sendMailCron.sendFinalMail(); return true; } + + @Operation(summary = "모집 알림 신청 메일 전송", description = "모집 시작 알림을 메일로 전송합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "500", content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @PostMapping("/recruit") + public boolean sendRecruitMail() { + sendMailCron.sendRecruitMail(); + return true; + } + + @Operation(summary = "모집 알림 신청 메일 등록", description = "모집 시작 알림을 받을 메일을 등록합니다.") + @ApiResponses({ + @ApiResponse(responseCode = "200"), + @ApiResponse(responseCode = "401", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "403", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "404", content = @Content(schema = @Schema(implementation = ErrorResponse.class))), + @ApiResponse(responseCode = "500", content = @Content(schema = @Schema(implementation = ErrorResponse.class))) + }) + @PostMapping("/subscribe") + public boolean subscribeRecruitMail(@RequestBody RecruitMailRequest request) { + subscribeRecruitMail.execute(request); + return true; + } } From 8d8cb1b0c19cf663bf4c08b1095e77b90d8257c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 18:07:55 +0900 Subject: [PATCH 02/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EB=A9=94=EC=9D=BC=20=EC=97=94=ED=8B=B0=ED=8B=B0=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leets/domain/mail/domain/RecruitMail.java | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/main/java/land/leets/domain/mail/domain/RecruitMail.java diff --git a/src/main/java/land/leets/domain/mail/domain/RecruitMail.java b/src/main/java/land/leets/domain/mail/domain/RecruitMail.java new file mode 100644 index 0000000..cca2631 --- /dev/null +++ b/src/main/java/land/leets/domain/mail/domain/RecruitMail.java @@ -0,0 +1,19 @@ +package land.leets.domain.mail.domain; + +import jakarta.persistence.*; +import land.leets.domain.shared.BaseTimeEntity; +import lombok.*; + +@Entity(name = "recruit_mails") +@Getter +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor +public class RecruitMail extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false) + private String email; +} From b192fe95027512b05ed18cf2f65d664f40a13db1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 18:26:35 +0900 Subject: [PATCH 03/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=9E=8C=20=EC=8B=A0=EC=B2=AD=20=EB=A9=94=EC=9D=BC=20=ED=81=AC?= =?UTF-8?q?=EB=A1=A0=EC=9E=A1=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/land/leets/domain/mail/usecase/SendMailCron.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java b/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java index 3de88e3..2e08bc1 100644 --- a/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java +++ b/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java @@ -13,6 +13,7 @@ public class SendMailCron { private final SendFinalMailImpl sendFinalMailImpl; private final SendPaperMailImpl sendPaperMailImpl; + private final SendRecruitMailImpl sendRecruitMail; // @Scheduled(cron = "0 0 23 8 9 ?") public void sendPaperMail() { @@ -43,5 +44,12 @@ public void sendFinalMail() { public void sendPlusMail() { log.info("Send final result mail successfully."); } + + // @Scheduled(cron = "0 0 00 ?? 3 ?") + public void sendRecruitMail() { + sendRecruitMail.execute(); + + log.info("Send recruit result mail successfully."); + } } From f69a83c1914044c5523d49a735530f6adc22720b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 21:42:39 +0900 Subject: [PATCH 04/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=9E=8C=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=ED=8F=BC=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 --- src/main/resources/templates/Recruit.html | 132 ++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 src/main/resources/templates/Recruit.html diff --git a/src/main/resources/templates/Recruit.html b/src/main/resources/templates/Recruit.html new file mode 100644 index 0000000..59ed40b --- /dev/null +++ b/src/main/resources/templates/Recruit.html @@ -0,0 +1,132 @@ + + + + + + Leets 모집 시작 안내 + + +
+ + + + +
+ logo + Leets +
+ + + + + + + + + + + +
+ 안녕하세요. Leets입니다. +
+ Leets 5기 모집에 관심을 가져주셔서 진심으로 감사드립니다. +
+
+ 금일부로 Leets 5기 모집이 시작되었습니다! +
+
+ Leets는 네트워킹과 협업을 통한 공동체 기반의 성장을 목표로 하고 있습니다. +
+ 학기 중에 쌓은 성장을 바탕으로, 방학 동안 자신이 원하는 서비스를 직접 구현합니다. +
+
+ Leets는 책임감과 열정을 가진 여러분을 기다리고 있습니다. +
+ 함께 협력하며 성장하고, 새로운 도전을 통해 특별한 경험을 만들고 싶습니다. +
+
+
+ 모든 지원서는 공정하고 면밀하게 검토될 예정입니다. +
+
+ 지원하신 모든 분들께 좋은 결과가 있기를 바라겠습니다. +
+ 감사합니다. +
+ + 기 지원하기 + +
+
+ 카카오톡 문의: + https://pf.kakao.com/_LtLyG +
+
+
+ + From 3b6059c39b03a034ee0626be9044036a230ffbfb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 22:32:16 +0900 Subject: [PATCH 05/15] =?UTF-8?q?feat:=20RecruitMail=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20=EB=A6=AC=ED=8F=AC?= =?UTF-8?q?=EC=A7=80=ED=86=A0=EB=A6=AC=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../land/leets/domain/mail/domain/RecruitMail.java | 3 --- .../mail/domain/repository/RecruitMailRepository.java | 10 ++++++++++ 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java diff --git a/src/main/java/land/leets/domain/mail/domain/RecruitMail.java b/src/main/java/land/leets/domain/mail/domain/RecruitMail.java index cca2631..394a5cb 100644 --- a/src/main/java/land/leets/domain/mail/domain/RecruitMail.java +++ b/src/main/java/land/leets/domain/mail/domain/RecruitMail.java @@ -11,9 +11,6 @@ public class RecruitMail extends BaseTimeEntity { @Id - @GeneratedValue(strategy = GenerationType.IDENTITY) - private Long id; - @Column(nullable = false) private String email; } diff --git a/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java b/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java new file mode 100644 index 0000000..6313879 --- /dev/null +++ b/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java @@ -0,0 +1,10 @@ +package land.leets.domain.mail.domain.repository; + +import land.leets.domain.mail.domain.RecruitMail; +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.List; + +public interface RecruitMailRepository extends JpaRepository { + List findAll(); +} From 6d8012343ccd8e2c4dfd51f941b9fa184fd8b91f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 22:36:38 +0900 Subject: [PATCH 06/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EB=A9=94=EC=9D=BC=20=EB=B0=9C=EC=86=A1=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/mail/usecase/SendMailCron.java | 3 +- .../domain/mail/usecase/SendRecruitMail.java | 43 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java diff --git a/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java b/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java index 2e08bc1..3d7282e 100644 --- a/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java +++ b/src/main/java/land/leets/domain/mail/usecase/SendMailCron.java @@ -1,5 +1,6 @@ package land.leets.domain.mail.usecase; +import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import land.leets.domain.application.type.ApplicationStatus; @@ -13,7 +14,7 @@ public class SendMailCron { private final SendFinalMailImpl sendFinalMailImpl; private final SendPaperMailImpl sendPaperMailImpl; - private final SendRecruitMailImpl sendRecruitMail; + private final SendRecruitMail sendRecruitMail; // @Scheduled(cron = "0 0 23 8 9 ?") public void sendPaperMail() { diff --git a/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java b/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java new file mode 100644 index 0000000..696994b --- /dev/null +++ b/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java @@ -0,0 +1,43 @@ +package land.leets.domain.mail.usecase; + +import land.leets.domain.mail.domain.Mail; +import land.leets.domain.mail.domain.repository.RecruitMailRepository; +import land.leets.domain.mail.service.MailManager; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.thymeleaf.TemplateEngine; +import org.thymeleaf.context.Context; + +import java.util.List; + +@RequiredArgsConstructor +@Service +@Transactional +public class SendRecruitMail { + private static final String MAIL_TITLE = "[Leets] 5기 모집 시작 안내 메일입니다."; + private static final String GENERATION_FIELD = "generation"; + private static final String TEMPLATE = "Recruit.html"; + + private final RecruitMailRepository recruitMailRepository; + private final TemplateEngine templateEngine; + private final MailManager mailManager; + + public void execute() { + List mails = recruitMailRepository.findAll().stream() + .map(recruitMail -> { + Context context = makeContext(); + String message = templateEngine.process(TEMPLATE, context); + return new Mail(MAIL_TITLE, recruitMail.getEmail(), message); + }) + .toList(); + + mailManager.sendEmails(mails); + } + + private Context makeContext() { + Context context = new Context(); + context.setVariable(GENERATION_FIELD, 5); + return context; + } +} From f3521971801aaaaaaf1a09212157f7ecab3d8264 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Mon, 2 Dec 2024 22:37:27 +0900 Subject: [PATCH 07/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20=EC=8B=A0=EC=B2=AD=20=EB=A1=9C=EC=A7=81=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 --- .../mail/usecase/SubscribeRecruitMail.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java diff --git a/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java b/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java new file mode 100644 index 0000000..ee8deea --- /dev/null +++ b/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java @@ -0,0 +1,20 @@ +package land.leets.domain.mail.usecase; + +import land.leets.domain.mail.controller.dto.RecruitMailRequest; +import land.leets.domain.mail.domain.RecruitMail; +import land.leets.domain.mail.domain.repository.RecruitMailRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@RequiredArgsConstructor +@Service +public class SubscribeRecruitMail { + + private final RecruitMailRepository recruitMailRepository; + + public void execute(RecruitMailRequest request) { + RecruitMail recruitMail = new RecruitMail(request.email()); + + recruitMailRepository.save(recruitMail); + } +} From 4cceff644e4ecfa3e6b18afbe31ff14ac04c8301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Tue, 3 Dec 2024 00:36:26 +0900 Subject: [PATCH 08/15] =?UTF-8?q?feat:=20=EB=AA=A8=EC=A7=91=20=EC=95=8C?= =?UTF-8?q?=EB=A6=BC=20DTO=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leets/domain/mail/controller/MailController.java | 3 ++- .../domain/mail/controller/dto/RecruitMailRequest.java | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java diff --git a/src/main/java/land/leets/domain/mail/controller/MailController.java b/src/main/java/land/leets/domain/mail/controller/MailController.java index bb4e158..445e651 100644 --- a/src/main/java/land/leets/domain/mail/controller/MailController.java +++ b/src/main/java/land/leets/domain/mail/controller/MailController.java @@ -1,5 +1,6 @@ package land.leets.domain.mail.controller; +import jakarta.validation.Valid; import land.leets.domain.mail.controller.dto.RecruitMailRequest; import land.leets.domain.mail.usecase.SubscribeRecruitMail; import org.springframework.web.bind.annotation.PostMapping; @@ -75,7 +76,7 @@ public boolean sendRecruitMail() { @ApiResponse(responseCode = "500", content = @Content(schema = @Schema(implementation = ErrorResponse.class))) }) @PostMapping("/subscribe") - public boolean subscribeRecruitMail(@RequestBody RecruitMailRequest request) { + public boolean subscribeRecruitMail(@Valid @RequestBody RecruitMailRequest request) { subscribeRecruitMail.execute(request); return true; } diff --git a/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java b/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java new file mode 100644 index 0000000..6888512 --- /dev/null +++ b/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java @@ -0,0 +1,9 @@ +package land.leets.domain.mail.controller.dto; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; + +public record RecruitMailRequest( + @Email @NotBlank String email +) { +} From 48ac48d9adb8893bb61689ff2691fe9e705bd770 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Tue, 3 Dec 2024 00:44:04 +0900 Subject: [PATCH 09/15] =?UTF-8?q?feat:=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20?= =?UTF-8?q?=EC=A4=91=EB=B3=B5=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 --- .../mail/domain/repository/RecruitMailRepository.java | 2 ++ .../mail/exception/MailAlreadyExistsException.java | 10 ++++++++++ .../domain/mail/usecase/SubscribeRecruitMail.java | 4 ++++ .../java/land/leets/global/config/SecurityConfig.java | 1 + src/main/java/land/leets/global/error/ErrorCode.java | 1 + 5 files changed, 18 insertions(+) create mode 100644 src/main/java/land/leets/domain/mail/exception/MailAlreadyExistsException.java diff --git a/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java b/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java index 6313879..0702ee8 100644 --- a/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java +++ b/src/main/java/land/leets/domain/mail/domain/repository/RecruitMailRepository.java @@ -7,4 +7,6 @@ public interface RecruitMailRepository extends JpaRepository { List findAll(); + + boolean existsByEmail(String email); } diff --git a/src/main/java/land/leets/domain/mail/exception/MailAlreadyExistsException.java b/src/main/java/land/leets/domain/mail/exception/MailAlreadyExistsException.java new file mode 100644 index 0000000..611933b --- /dev/null +++ b/src/main/java/land/leets/domain/mail/exception/MailAlreadyExistsException.java @@ -0,0 +1,10 @@ +package land.leets.domain.mail.exception; + +import land.leets.global.error.ErrorCode; +import land.leets.global.error.exception.ServiceException; + +public class MailAlreadyExistsException extends ServiceException { + public MailAlreadyExistsException() { + super(ErrorCode.EMAIL_ALREADY_EXISTS); + } +} diff --git a/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java b/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java index ee8deea..b946806 100644 --- a/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java +++ b/src/main/java/land/leets/domain/mail/usecase/SubscribeRecruitMail.java @@ -3,6 +3,7 @@ import land.leets.domain.mail.controller.dto.RecruitMailRequest; import land.leets.domain.mail.domain.RecruitMail; import land.leets.domain.mail.domain.repository.RecruitMailRepository; +import land.leets.domain.mail.exception.MailAlreadyExistsException; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Service; @@ -13,6 +14,9 @@ public class SubscribeRecruitMail { private final RecruitMailRepository recruitMailRepository; public void execute(RecruitMailRequest request) { + if (recruitMailRepository.existsByEmail(request.email())) { + throw new MailAlreadyExistsException(); + } RecruitMail recruitMail = new RecruitMail(request.email()); recruitMailRepository.save(recruitMail); diff --git a/src/main/java/land/leets/global/config/SecurityConfig.java b/src/main/java/land/leets/global/config/SecurityConfig.java index 5aa57a7..aee8dd0 100644 --- a/src/main/java/land/leets/global/config/SecurityConfig.java +++ b/src/main/java/land/leets/global/config/SecurityConfig.java @@ -81,6 +81,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { .requestMatchers("/comments/**").hasAuthority(AuthRole.ROLE_ADMIN.getRole()) + .requestMatchers(HttpMethod.POST, "/mail/subscribe").permitAll() .requestMatchers(HttpMethod.POST, "/mail/**").hasAuthority(AuthRole.ROLE_ADMIN.getRole()) .requestMatchers("/portfolios/**").permitAll() diff --git a/src/main/java/land/leets/global/error/ErrorCode.java b/src/main/java/land/leets/global/error/ErrorCode.java index 9a537e6..c768545 100644 --- a/src/main/java/land/leets/global/error/ErrorCode.java +++ b/src/main/java/land/leets/global/error/ErrorCode.java @@ -10,6 +10,7 @@ public enum ErrorCode { PATCH_REQUEST_FAIL(404, "PATCH_REQUEST_FAIL", "PATCH 요청에 실패했습니다."), INTERVIEW_NOT_FOUND(404, "INTERVIEW_NOT_FOUND", "면접 정보를 찾을 수 없습니다."), APPLICATION_ALREADY_EXISTS(409, "APPLICATION_ALREADY_EXISTS", "이미 지원한 지원자입니다."), + EMAIL_ALREADY_EXISTS(409, "EMAIL_ALREADY_EXISTS", "이미 등록한 이메일입니다."), PERMISSION_DENIED(403, "PERMISSION_DENIED", "권한이 없습니다."), APPLICATION_NOT_FOUND(404, "APPLICATION_NOT_FOUND", "신청서를 찾을 수 없습니다."), PASSWORD_NOT_MATCH(403, "PASSWORD_NOT_MATCH", "비밀번호가 일치하지 않습니다."), From a8e7775503f34915bd559330869e09d679386b6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Tue, 3 Dec 2024 01:03:35 +0900 Subject: [PATCH 10/15] =?UTF-8?q?feat:=20=EA=B2=80=EC=A6=9D=20=EB=A1=9C?= =?UTF-8?q?=EC=A7=81=20=EC=98=88=EC=99=B8=EC=B2=98=EB=A6=AC=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leets/global/advice/ExceptionHandleAdvice.java | 13 +++++++++++++ .../leets/global/error/BindExceptionResponse.java | 7 +++++++ 2 files changed, 20 insertions(+) create mode 100644 src/main/java/land/leets/global/error/BindExceptionResponse.java diff --git a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java index c214ce9..87a7921 100644 --- a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java +++ b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java @@ -1,9 +1,12 @@ package land.leets.global.advice; +import land.leets.global.error.BindExceptionResponse; import land.leets.global.error.ErrorCode; import land.leets.global.error.ErrorResponse; import land.leets.global.error.exception.ServiceException; import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingRequestCookieException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; @@ -29,4 +32,14 @@ public ResponseEntity handleException(Exception ex) { ErrorResponse response = new ErrorResponse(ErrorCode.INTERNAL_SERVER_ERROR); return ResponseEntity.internalServerError().body(response); } + + @ExceptionHandler(MethodArgumentNotValidException.class) + public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex) { + String message = ex.getBindingResult().getFieldErrors().stream() + .findFirst() + .map(FieldError::getDefaultMessage) + .orElseThrow(); + BindExceptionResponse response = new BindExceptionResponse(ex.getStatusCode().value(), message); + return ResponseEntity.status(ex.getStatusCode()).body(response); + } } diff --git a/src/main/java/land/leets/global/error/BindExceptionResponse.java b/src/main/java/land/leets/global/error/BindExceptionResponse.java new file mode 100644 index 0000000..454fabb --- /dev/null +++ b/src/main/java/land/leets/global/error/BindExceptionResponse.java @@ -0,0 +1,7 @@ +package land.leets.global.error; + +public record BindExceptionResponse( + int httpStatus, + String message +) { +} From 0a88806f3c40ce6f15b79b4fd8fdc12f4e2672a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Tue, 3 Dec 2024 13:44:17 +0900 Subject: [PATCH 11/15] =?UTF-8?q?style:=20=EC=BB=A8=EB=B2=A4=EC=85=98=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../leets/domain/mail/controller/dto/RecruitMailRequest.java | 4 +++- .../java/land/leets/domain/mail/usecase/SendRecruitMail.java | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java b/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java index 6888512..9d06314 100644 --- a/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java +++ b/src/main/java/land/leets/domain/mail/controller/dto/RecruitMailRequest.java @@ -4,6 +4,8 @@ import jakarta.validation.constraints.NotBlank; public record RecruitMailRequest( - @Email @NotBlank String email + @Email + @NotBlank + String email ) { } diff --git a/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java b/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java index 696994b..1265b74 100644 --- a/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java +++ b/src/main/java/land/leets/domain/mail/usecase/SendRecruitMail.java @@ -15,6 +15,7 @@ @Service @Transactional public class SendRecruitMail { + private static final String MAIL_TITLE = "[Leets] 5기 모집 시작 안내 메일입니다."; private static final String GENERATION_FIELD = "generation"; private static final String TEMPLATE = "Recruit.html"; From 2ba095af09176f55822fa62d3579d3d369a4725b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Thu, 5 Dec 2024 16:47:06 +0900 Subject: [PATCH 12/15] =?UTF-8?q?fix:=20=EC=97=90=EB=9F=AC=20=EC=9D=91?= =?UTF-8?q?=EB=8B=B5=20=EA=B0=9D=EC=B2=B4=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../land/leets/global/error/BindExceptionResponse.java | 7 ------- src/main/java/land/leets/global/error/ErrorResponse.java | 6 ++++++ 2 files changed, 6 insertions(+), 7 deletions(-) delete mode 100644 src/main/java/land/leets/global/error/BindExceptionResponse.java diff --git a/src/main/java/land/leets/global/error/BindExceptionResponse.java b/src/main/java/land/leets/global/error/BindExceptionResponse.java deleted file mode 100644 index 454fabb..0000000 --- a/src/main/java/land/leets/global/error/BindExceptionResponse.java +++ /dev/null @@ -1,7 +0,0 @@ -package land.leets.global.error; - -public record BindExceptionResponse( - int httpStatus, - String message -) { -} diff --git a/src/main/java/land/leets/global/error/ErrorResponse.java b/src/main/java/land/leets/global/error/ErrorResponse.java index 069ec60..b197655 100644 --- a/src/main/java/land/leets/global/error/ErrorResponse.java +++ b/src/main/java/land/leets/global/error/ErrorResponse.java @@ -15,6 +15,12 @@ public ErrorResponse(ErrorCode errorCode) { this.code = errorCode.getCode(); } + public ErrorResponse(ErrorCode errorCode, String customMessage) { + this.httpStatus = errorCode.getHttpStatus(); + this.message = customMessage; + this.code = errorCode.getCode(); + } + public static ErrorResponse of(ErrorCode errorCode) { return new ErrorResponse(errorCode); } From e9a32acbc10935e028e1c88e5c46029de60e5133 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Thu, 5 Dec 2024 16:49:02 +0900 Subject: [PATCH 13/15] =?UTF-8?q?feat:=20=EC=97=90=EB=9F=AC=20=EC=BD=94?= =?UTF-8?q?=EB=93=9C=EC=97=90=20=EA=B2=80=EC=A6=9D=20=EC=8B=A4=ED=8C=A8=20?= =?UTF-8?q?=ED=95=84=EB=93=9C=20=EB=B0=98=EC=98=81=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../global/advice/ExceptionHandleAdvice.java | 24 +++++++++++-------- .../land/leets/global/error/ErrorCode.java | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java index 87a7921..157173e 100644 --- a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java +++ b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java @@ -1,19 +1,19 @@ package land.leets.global.advice; -import land.leets.global.error.BindExceptionResponse; import land.leets.global.error.ErrorCode; import land.leets.global.error.ErrorResponse; import land.leets.global.error.exception.ServiceException; import org.springframework.http.ResponseEntity; -import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingRequestCookieException; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; +import java.util.stream.Collectors; + @RestControllerAdvice public class ExceptionHandleAdvice { - + @ExceptionHandler(ServiceException.class) public ResponseEntity handleServiceException(ServiceException ex) { ErrorResponse response = new ErrorResponse(ex.getErrorCode()); @@ -34,12 +34,16 @@ public ResponseEntity handleException(Exception ex) { } @ExceptionHandler(MethodArgumentNotValidException.class) - public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex) { - String message = ex.getBindingResult().getFieldErrors().stream() - .findFirst() - .map(FieldError::getDefaultMessage) - .orElseThrow(); - BindExceptionResponse response = new BindExceptionResponse(ex.getStatusCode().value(), message); - return ResponseEntity.status(ex.getStatusCode()).body(response); + public ResponseEntity handleValidationExceptions(MethodArgumentNotValidException ex) { + String fieldErrors = ex.getBindingResult() + .getFieldErrors() + .stream() + .map(fieldError -> String.format("%s", fieldError.getField())) + .collect(Collectors.joining(", ")); + + String customMessage = String.format(ErrorCode.INVALID_REQUEST_BODY.getMessage(), fieldErrors); + ErrorResponse response = new ErrorResponse(ErrorCode.INVALID_REQUEST_BODY, customMessage); + + return ResponseEntity.status(ErrorCode.INVALID_REQUEST_BODY.getHttpStatus()).body(response); } } diff --git a/src/main/java/land/leets/global/error/ErrorCode.java b/src/main/java/land/leets/global/error/ErrorCode.java index c768545..14da5dd 100644 --- a/src/main/java/land/leets/global/error/ErrorCode.java +++ b/src/main/java/land/leets/global/error/ErrorCode.java @@ -7,6 +7,7 @@ @AllArgsConstructor public enum ErrorCode { + INVALID_REQUEST_BODY(400, "INVALID_REQUEST_BODY", "올바르지 않은 요청입니다 [%s]"), PATCH_REQUEST_FAIL(404, "PATCH_REQUEST_FAIL", "PATCH 요청에 실패했습니다."), INTERVIEW_NOT_FOUND(404, "INTERVIEW_NOT_FOUND", "면접 정보를 찾을 수 없습니다."), APPLICATION_ALREADY_EXISTS(409, "APPLICATION_ALREADY_EXISTS", "이미 지원한 지원자입니다."), From ca44408a3ef734d38fc0bdb1fe36b5a5743f96d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Thu, 5 Dec 2024 16:53:29 +0900 Subject: [PATCH 14/15] =?UTF-8?q?feat:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=ED=8F=AC=EB=A7=B7=20=EC=97=B0=EC=82=B0=EC=9E=90=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 --- .../java/land/leets/global/advice/ExceptionHandleAdvice.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java index 157173e..60f4124 100644 --- a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java +++ b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java @@ -38,7 +38,7 @@ public ResponseEntity handleValidationExceptions(MethodArgumentNo String fieldErrors = ex.getBindingResult() .getFieldErrors() .stream() - .map(fieldError -> String.format("%s", fieldError.getField())) + .map(fieldError -> String.format(fieldError.getField())) .collect(Collectors.joining(", ")); String customMessage = String.format(ErrorCode.INVALID_REQUEST_BODY.getMessage(), fieldErrors); From 2b35562a49e8d6a37eb8cc21243c38049e050a1c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EB=85=B8=EC=A0=95=EC=99=84?= Date: Thu, 5 Dec 2024 17:14:25 +0900 Subject: [PATCH 15/15] =?UTF-8?q?fix:=20Strig=20format=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/land/leets/global/advice/ExceptionHandleAdvice.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java index 60f4124..b1b6aff 100644 --- a/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java +++ b/src/main/java/land/leets/global/advice/ExceptionHandleAdvice.java @@ -4,6 +4,7 @@ import land.leets.global.error.ErrorResponse; import land.leets.global.error.exception.ServiceException; import org.springframework.http.ResponseEntity; +import org.springframework.validation.FieldError; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingRequestCookieException; import org.springframework.web.bind.annotation.ExceptionHandler; @@ -38,7 +39,7 @@ public ResponseEntity handleValidationExceptions(MethodArgumentNo String fieldErrors = ex.getBindingResult() .getFieldErrors() .stream() - .map(fieldError -> String.format(fieldError.getField())) + .map(FieldError::getField) .collect(Collectors.joining(", ")); String customMessage = String.format(ErrorCode.INVALID_REQUEST_BODY.getMessage(), fieldErrors);