-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- 알림 관련 클래스 추가: NotificationType, NotificationEvent, TemplateProcessor - Thymeleaf, AWS SES 의존성 추가 및 관련 설정 클래스 구현 - 알림 이벤트 리스너와 이메일 템플릿 추가, 사용자 승인/거절 API에 이메일 발송 로직 구현 - 알림 관련 에러 코드 및 커스텀 예외 클래스 추가, EmailService 예외 처리 개선 - 비동기 처리를 위한 AsyncConfig 추가
- Loading branch information
Showing
16 changed files
with
448 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
21 changes: 21 additions & 0 deletions
21
src/main/java/com/example/epari/admin/dto/RejectionRequestDTO.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package com.example.epari.admin.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Data; | ||
import lombok.NoArgsConstructor; | ||
|
||
/** | ||
* 사용자 반려 요청 DTO | ||
*/ | ||
@Data | ||
@AllArgsConstructor | ||
@NoArgsConstructor | ||
public class RejectionRequestDTO { | ||
|
||
private String username; // Cognito username | ||
|
||
private String name; // Username | ||
|
||
private String reason; // 반려 사유 | ||
|
||
} |
15 changes: 15 additions & 0 deletions
15
src/main/java/com/example/epari/admin/exception/NotificationException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
package com.example.epari.admin.exception; | ||
|
||
import com.example.epari.global.exception.BusinessBaseException; | ||
import com.example.epari.global.exception.ErrorCode; | ||
|
||
/** | ||
* 알림 관련 커스텀 예외 | ||
*/ | ||
public class NotificationException extends BusinessBaseException { | ||
|
||
public NotificationException(ErrorCode errorCode) { | ||
super(errorCode); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
10 changes: 10 additions & 0 deletions
10
src/main/java/com/example/epari/global/config/AsyncConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
package com.example.epari.global.config; | ||
|
||
import org.springframework.context.annotation.Configuration; | ||
import org.springframework.scheduling.annotation.EnableAsync; | ||
|
||
@Configuration | ||
@EnableAsync | ||
public class AsyncConfig { | ||
|
||
} |
36 changes: 36 additions & 0 deletions
36
src/main/java/com/example/epari/global/config/ThymeleafConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package com.example.epari.global.config; | ||
|
||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
import org.thymeleaf.spring6.SpringTemplateEngine; | ||
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver; | ||
import org.thymeleaf.templateresolver.ITemplateResolver; | ||
|
||
/** | ||
* Thymeleaf 관련 설정 클래스 | ||
*/ | ||
@Configuration | ||
public class ThymeleafConfig { | ||
|
||
@Bean | ||
public SpringTemplateEngine emailTemplateEngine() { | ||
SpringTemplateEngine templateEngine = new SpringTemplateEngine(); | ||
|
||
templateEngine.setTemplateResolver(emailTemplateResolver()); | ||
|
||
return templateEngine; | ||
} | ||
|
||
@Bean | ||
public ITemplateResolver emailTemplateResolver() { | ||
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver(); | ||
|
||
templateResolver.setPrefix("mail-templates/"); | ||
templateResolver.setSuffix(".html"); | ||
templateResolver.setTemplateMode("HTML"); | ||
templateResolver.setCharacterEncoding("UTF-8"); | ||
|
||
return templateResolver; | ||
} | ||
|
||
} |
32 changes: 32 additions & 0 deletions
32
src/main/java/com/example/epari/global/config/aws/AwsSesConfig.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package com.example.epari.global.config.aws; | ||
|
||
import org.springframework.boot.context.properties.EnableConfigurationProperties; | ||
import org.springframework.context.annotation.Bean; | ||
import org.springframework.context.annotation.Configuration; | ||
|
||
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials; | ||
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider; | ||
import software.amazon.awssdk.regions.Region; | ||
import software.amazon.awssdk.services.ses.SesClient; | ||
|
||
/** | ||
* AWS SES 사용을 위한 설정 클래스 | ||
*/ | ||
@Configuration | ||
@EnableConfigurationProperties(AwsS3Properties.class) | ||
public class AwsSesConfig { | ||
|
||
@Bean | ||
public SesClient sesClient(AwsS3Properties properties) { | ||
return SesClient.builder() | ||
.region(Region.of(properties.getRegion())) | ||
.credentialsProvider(StaticCredentialsProvider.create( | ||
AwsBasicCredentials.create( | ||
properties.getAccessKey(), | ||
properties.getSecretKey() | ||
) | ||
)) | ||
.build(); | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
src/main/java/com/example/epari/global/event/NotificationEvent.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.example.epari.global.event; | ||
|
||
import java.util.HashMap; | ||
import java.util.Map; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
|
||
/** | ||
* 알림 이벤트 클래스 | ||
*/ | ||
@Getter | ||
@Builder | ||
public class NotificationEvent { | ||
|
||
private String to; | ||
|
||
private NotificationType type; | ||
|
||
private Map<String, String> properties; | ||
|
||
public static NotificationEvent of(String to, NotificationType type) { | ||
return NotificationEvent.builder() | ||
.to(to) | ||
.type(type) | ||
.properties(new HashMap<>()) | ||
.build(); | ||
} | ||
|
||
public NotificationEvent addProperty(String key, String value) { | ||
this.properties.put(key, value); | ||
return this; | ||
} | ||
|
||
} |
23 changes: 23 additions & 0 deletions
23
src/main/java/com/example/epari/global/event/NotificationType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package com.example.epari.global.event; | ||
|
||
import lombok.Getter; | ||
|
||
/** | ||
* 알림 타입 Enum 클래스 | ||
*/ | ||
@Getter | ||
public enum NotificationType { | ||
|
||
USER_APPROVED("사용자 승인", "user-approved.html"), | ||
USER_REJECTED("사용자 반려", "user-rejected.html"); | ||
|
||
private final String description; | ||
|
||
private final String templatePath; | ||
|
||
NotificationType(String description, String templatePath) { | ||
this.description = description; | ||
this.templatePath = templatePath; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
src/main/java/com/example/epari/global/notification/EmailService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
package com.example.epari.global.notification; | ||
|
||
import org.springframework.beans.factory.annotation.Value; | ||
import org.springframework.stereotype.Service; | ||
|
||
import com.example.epari.admin.exception.NotificationException; | ||
import com.example.epari.global.event.NotificationEvent; | ||
import com.example.epari.global.exception.ErrorCode; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import software.amazon.awssdk.services.ses.SesClient; | ||
import software.amazon.awssdk.services.ses.model.Body; | ||
import software.amazon.awssdk.services.ses.model.Content; | ||
import software.amazon.awssdk.services.ses.model.Destination; | ||
import software.amazon.awssdk.services.ses.model.Message; | ||
import software.amazon.awssdk.services.ses.model.SendEmailRequest; | ||
import software.amazon.awssdk.services.ses.model.SesException; | ||
|
||
/** | ||
* 이메일 전송을 담당하는 서비스 클래스 | ||
*/ | ||
@Slf4j | ||
@Service | ||
@RequiredArgsConstructor | ||
public class EmailService { | ||
|
||
private final SesClient sesClient; | ||
|
||
private final TemplateProcessor templateProcessor; | ||
|
||
@Value("${aws.ses.source.email}") | ||
private String sender; | ||
|
||
/** | ||
* 이벤트를 기반으로 이메일을 발송 | ||
*/ | ||
public void sendEmail(NotificationEvent event) { | ||
try { | ||
String content = templateProcessor.processTemplate( | ||
event.getType(), | ||
event.getProperties() | ||
); | ||
|
||
SendEmailRequest request = SendEmailRequest.builder() | ||
.source(sender) | ||
.destination(Destination.builder() | ||
.toAddresses(event.getTo()) | ||
.build()) | ||
.message(Message.builder() | ||
.subject(Content.builder() | ||
.data(event.getType().getDescription()) | ||
.build()) | ||
.body(Body.builder() | ||
.html(Content.builder() | ||
.data(content) | ||
.build()) | ||
.build()) | ||
.build()) | ||
.build(); | ||
|
||
sesClient.sendEmail(request); | ||
log.info("Email sent successfully to: {}", event.getTo()); | ||
} catch (SesException e) { | ||
log.error("AWS SES error for: {}", event.getTo(), e); | ||
throw new NotificationException(ErrorCode.SES_SERVICE_ERROR); | ||
} catch (Exception e) { | ||
log.error("Notification failed for: {}", event.getTo(), e); | ||
throw new NotificationException(ErrorCode.NOTIFICATION_SEND_FAILED); | ||
} | ||
} | ||
|
||
} |
33 changes: 33 additions & 0 deletions
33
src/main/java/com/example/epari/global/notification/NotificationEventListener.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package com.example.epari.global.notification; | ||
|
||
import org.springframework.context.event.EventListener; | ||
import org.springframework.scheduling.annotation.Async; | ||
import org.springframework.stereotype.Component; | ||
|
||
import com.example.epari.global.event.NotificationEvent; | ||
|
||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
/** | ||
* 알림 이벤트를 Listen하는 이벤트 리스너 클래스 | ||
*/ | ||
@Component | ||
@RequiredArgsConstructor | ||
@Slf4j | ||
public class NotificationEventListener { | ||
|
||
private final EmailService emailService; | ||
|
||
/** | ||
* NotificationEvent를 처리하는 메서드 | ||
* emailService.sendEmail 메서드 호출 | ||
*/ | ||
@Async | ||
@EventListener | ||
public void handleNotificationEvent(NotificationEvent event) { | ||
log.info("Received notification event for: {}", event.getTo()); | ||
emailService.sendEmail(event); | ||
} | ||
|
||
} |
Oops, something went wrong.