From b1dc050f70bcf33de37e75bdcf4ae4a52ee65b42 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Thu, 4 Apr 2024 18:16:02 +0900 Subject: [PATCH 01/42] =?UTF-8?q?feat:=20question=20=EC=97=94=ED=8B=B0?= =?UTF-8?q?=ED=8B=B0,=20repository=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domains/question/domain/Question.java | 34 +++++++++++++++++++ .../question/domain/QuestionCategory.java | 16 +++++++++ .../repository/QuestionRepository.java | 7 ++++ 3 files changed, 57 insertions(+) create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/repository/QuestionRepository.java diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java new file mode 100644 index 000000000..fbed816ba --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java @@ -0,0 +1,34 @@ +package kr.co.pennyway.domain.domains.question.domain; + +import jakarta.persistence.*; +import kr.co.pennyway.domain.domains.user.domain.User; +import lombok.AccessLevel; +import lombok.Getter; +import lombok.NoArgsConstructor; +import org.hibernate.annotations.ColumnDefault; +import org.springframework.data.annotation.CreatedDate; + +import java.time.LocalDateTime; + +@Entity +@Getter +@Table(name = "Question") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +public class Question { + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + private String email; + + private QuestionCategory category; + private String content; + + + @CreatedDate + @Column(name = "created_at", nullable = false, updatable = false) + private LocalDateTime createdAt; + + @ColumnDefault("NULL") + private LocalDateTime deletedAt; +} diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java new file mode 100644 index 000000000..c7e310547 --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java @@ -0,0 +1,16 @@ +package kr.co.pennyway.domain.domains.question.domain; + +import lombok.AccessLevel; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor(access = AccessLevel.PRIVATE) +@Getter +public enum QuestionCategory { + UTILIZATION("이용 관련"), + BUG_REPORT("오류 신고"), + SUGGESTION("서비스 제안"), + ETC("기타"); + + private final String title; +} diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/repository/QuestionRepository.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/repository/QuestionRepository.java new file mode 100644 index 000000000..d50f22cdd --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/repository/QuestionRepository.java @@ -0,0 +1,7 @@ +package kr.co.pennyway.domain.domains.question.repository; + +import kr.co.pennyway.domain.domains.question.domain.Question; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface QuestionRepository extends JpaRepository { +} From 7a0a59bee879d92e7d9af4b6291c5d71902c6af2 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Fri, 5 Apr 2024 03:24:46 +0900 Subject: [PATCH 02/42] =?UTF-8?q?feat:=20mail=20=EB=B0=9C=EC=86=A1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EC=9E=84=EC=8B=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pennyway-app-external-api/build.gradle | 1 + .../controller/QuestionController.java | 33 +++++++++++++++++++ .../api/apis/question/dto/QuestionReq.java | 23 +++++++++++++ .../question/usecase/QuestionUseCase.java | 33 +++++++++++++++++++ .../domains/question/domain/Question.java | 10 ++++++ .../question/domain/QuestionCategory.java | 6 ++++ 6 files changed, 106 insertions(+) create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java diff --git a/pennyway-app-external-api/build.gradle b/pennyway-app-external-api/build.gradle index 2ae563a35..05182d0bc 100644 --- a/pennyway-app-external-api/build.gradle +++ b/pennyway-app-external-api/build.gradle @@ -29,4 +29,5 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.2.3' implementation 'org.springframework.boot:spring-boot-starter-validation:3.2.3' + implementation 'org.springframework.boot:spring-boot-starter-mail' } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java new file mode 100644 index 000000000..eebba8266 --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -0,0 +1,33 @@ +package kr.co.pennyway.api.apis.question.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import kr.co.pennyway.api.apis.question.dto.QuestionReq; +import kr.co.pennyway.api.apis.question.usecase.QuestionUseCase; +import kr.co.pennyway.api.common.response.SuccessResponse; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@Slf4j +@Tag(name = "[문의 API]") +@RestController +@RequiredArgsConstructor +@RequestMapping("/v1/question") +public class QuestionController { + private final QuestionUseCase questionUseCase; + + @Operation(summary = "문의 전송") + @GetMapping("/send") + @PreAuthorize("isAnonymous()") + public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request){ + questionUseCase.sendQuestion(request); + return ResponseEntity.ok(SuccessResponse.noContent()); + } +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java new file mode 100644 index 000000000..a2e5ec59e --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -0,0 +1,23 @@ +package kr.co.pennyway.api.apis.question.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import kr.co.pennyway.domain.domains.question.domain.Question; +import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; + +public class QuestionReq { + + @Schema(name = "QuestionReqGeneral", title = "문의 요청") + public record General( + String email, + String content, + QuestionCategory category + ){ + public Question toEntity(){ + return Question.builder() + .email(email) + .content(content) + .category(category) + .build(); + } + } +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java new file mode 100644 index 000000000..5adc68971 --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -0,0 +1,33 @@ +package kr.co.pennyway.api.apis.question.usecase; + +import kr.co.pennyway.api.apis.question.dto.QuestionReq; +import kr.co.pennyway.common.annotation.UseCase; +import lombok.AllArgsConstructor; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import jakarta.mail.internet.MimeMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; + +@Slf4j +@UseCase +@AllArgsConstructor +public class QuestionUseCase { + private final JavaMailSender javaMailSender; + + public void sendQuestion(QuestionReq.General request){ + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + + try{ + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); + helper.setTo(request.email()); + helper.setSubject("테스트용 이메일"); + helper.setText(request.content()); + javaMailSender.send(mimeMessage); + + } catch(Exception e) { + throw new IllegalArgumentException("tset"); + } + + } +} diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java index fbed816ba..28dc87bf7 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java @@ -3,6 +3,7 @@ import jakarta.persistence.*; import kr.co.pennyway.domain.domains.user.domain.User; import lombok.AccessLevel; +import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.hibernate.annotations.ColumnDefault; @@ -31,4 +32,13 @@ public class Question { @ColumnDefault("NULL") private LocalDateTime deletedAt; + + @Builder + private Question(String email, QuestionCategory category, String content, LocalDateTime createdAt, LocalDateTime deletedAt) { + this.email = email; + this.category = category; + this.content = content; + this.createdAt = createdAt; + this.deletedAt = deletedAt; + } } diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java index c7e310547..a79e972c1 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java @@ -4,6 +4,12 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; +/** + * 문의 요청 DTO + *
+ * 문의 요청시 사용됩니다. + */ + @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter public enum QuestionCategory { From 0defa67f9dd5e2cd917c63574c34eb12a225ba9e Mon Sep 17 00:00:00 2001 From: asn6878 Date: Fri, 5 Apr 2024 04:04:18 +0900 Subject: [PATCH 03/42] =?UTF-8?q?fix:=20http=20=EB=A9=94=EC=84=9C=EB=93=9C?= =?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 --- .../api/apis/question/controller/QuestionController.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index eebba8266..5a3dc7ebd 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -10,10 +10,7 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; @Slf4j @Tag(name = "[문의 API]") @@ -24,7 +21,7 @@ public class QuestionController { private final QuestionUseCase questionUseCase; @Operation(summary = "문의 전송") - @GetMapping("/send") + @PostMapping("/send") @PreAuthorize("isAnonymous()") public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request){ questionUseCase.sendQuestion(request); From 2b79e80fdf538b87342bb9b0089169540ca3a9ac Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 7 Apr 2024 05:15:17 +0900 Subject: [PATCH 04/42] =?UTF-8?q?feat:=20question=20=EC=98=88=EC=99=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question/exception/QuestionErrorCode.java | 26 +++++++++++++++++++ .../exception/QuestionErrorException.java | 24 +++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorException.java diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java new file mode 100644 index 000000000..c041d3760 --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java @@ -0,0 +1,26 @@ +package kr.co.pennyway.domain.domains.question.exception; + +import kr.co.pennyway.common.exception.BaseErrorCode; +import kr.co.pennyway.common.exception.CausedBy; +import kr.co.pennyway.common.exception.ReasonCode; +import kr.co.pennyway.common.exception.StatusCode; +import lombok.AllArgsConstructor; + +@AllArgsConstructor +public enum QuestionErrorCode implements BaseErrorCode { + INTERNAL_MAILERROR(StatusCode.INTERNAL_SERVER_ERROR, ReasonCode.UNEXPECTED_ERROR, "메일 발송에 실패했습니다."); + + private final StatusCode statusCode; + private final ReasonCode reasonCode; + private final String message; + + @Override + public CausedBy causedBy() { + return CausedBy.of(statusCode, reasonCode); + } + + @Override + public String getExplainError() throws NoSuchFieldError { + return message; + } +} diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorException.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorException.java new file mode 100644 index 000000000..3eb89c218 --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorException.java @@ -0,0 +1,24 @@ +package kr.co.pennyway.domain.domains.question.exception; + +import kr.co.pennyway.common.exception.BaseErrorCode; +import kr.co.pennyway.common.exception.CausedBy; +import kr.co.pennyway.common.exception.GlobalErrorException; +import kr.co.pennyway.domain.domains.user.exception.UserErrorCode; +import lombok.Getter; + +public class QuestionErrorException extends GlobalErrorException { + private final QuestionErrorCode questionErrorCode; + + public QuestionErrorException(QuestionErrorCode questionErrorCode) { + super(questionErrorCode); + this.questionErrorCode = questionErrorCode; + } + + public CausedBy causedBy() { + return questionErrorCode.causedBy(); + } + + public String getExplainError() { + return questionErrorCode.getExplainError(); + } +} From b628dc85d937c84622b48a6796f3677e499bf581 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 7 Apr 2024 05:15:58 +0900 Subject: [PATCH 05/42] =?UTF-8?q?feat:=20question=20service=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question/service/QuestionService.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java new file mode 100644 index 000000000..515ac4cd8 --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java @@ -0,0 +1,17 @@ +package kr.co.pennyway.domain.domains.question.service; + +import jakarta.transaction.Transactional; +import kr.co.pennyway.domain.domains.question.domain.Question; +import kr.co.pennyway.domain.domains.question.repository.QuestionRepository; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class QuestionService { + private final QuestionRepository questionRepository; + + @Transactional + public Question createQuestion(Question question) { return questionRepository.save(question);} + +} From 7571a8fbae71596d293307b0146b17e110f61e14 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 7 Apr 2024 06:00:48 +0900 Subject: [PATCH 06/42] =?UTF-8?q?feat:=20=EB=AC=B8=EC=9D=98=20=EB=B0=9C?= =?UTF-8?q?=EC=86=A1=20api=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/QuestionController.java | 5 +- .../apis/question/mapper/QuestionMapper.java | 49 +++++++++++++++++++ .../question/usecase/QuestionUseCase.java | 32 ++++++++---- 3 files changed, 74 insertions(+), 12 deletions(-) create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index 5a3dc7ebd..6e0ad9b14 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -5,6 +5,7 @@ import kr.co.pennyway.api.apis.question.dto.QuestionReq; import kr.co.pennyway.api.apis.question.usecase.QuestionUseCase; import kr.co.pennyway.api.common.response.SuccessResponse; +import kr.co.pennyway.domain.domains.question.domain.Question; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; @@ -24,7 +25,7 @@ public class QuestionController { @PostMapping("/send") @PreAuthorize("isAnonymous()") public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request){ - questionUseCase.sendQuestion(request); - return ResponseEntity.ok(SuccessResponse.noContent()); + Question question = questionUseCase.sendQuestion(request); + return ResponseEntity.ok(SuccessResponse.from(question)); } } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java new file mode 100644 index 000000000..fd47df0b4 --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -0,0 +1,49 @@ +package kr.co.pennyway.api.apis.question.mapper; + +import jakarta.mail.internet.MimeMessage; +import kr.co.pennyway.api.apis.question.dto.QuestionReq; +import kr.co.pennyway.common.annotation.Mapper; +import kr.co.pennyway.domain.domains.question.domain.Question; +import kr.co.pennyway.domain.domains.question.exception.QuestionErrorCode; +import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; +import kr.co.pennyway.domain.domains.question.service.QuestionService; +import lombok.AllArgsConstructor; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; + +@Mapper +@AllArgsConstructor +public class QuestionMapper { + private final JavaMailSender javaMailSender; + private final QuestionService questionService; + + /** + * + */ + public MimeMessage createMessage(QuestionReq.General request, String address){ + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + + try{ + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); + helper.setTo(address); + helper.setSubject("테스트용 이메일"); + helper.setText(request.content()); + + return mimeMessage; + } catch(Exception e) { + throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAILERROR); + } + + } + + /** + * Question 객체를 생성해 반환하며, DB에 저장한다. + */ + public Question createQuestion(QuestionReq.General request){ + Question question = request.toEntity(); + Question response = questionService.createQuestion(question); + + return response; + } + +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index 5adc68971..74f9a22a3 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -1,32 +1,44 @@ package kr.co.pennyway.api.apis.question.usecase; import kr.co.pennyway.api.apis.question.dto.QuestionReq; +import kr.co.pennyway.api.apis.question.mapper.QuestionMapper; import kr.co.pennyway.common.annotation.UseCase; +import kr.co.pennyway.domain.domains.question.domain.Question; +import kr.co.pennyway.domain.domains.question.exception.QuestionErrorCode; +import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import jakarta.mail.internet.MimeMessage; +import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; @Slf4j @UseCase -@AllArgsConstructor public class QuestionUseCase { private final JavaMailSender javaMailSender; + private final QuestionMapper questionMapper; + private String adminAddress; - public void sendQuestion(QuestionReq.General request){ - MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMapper, @Value("${app.question-address}") String adminAddress){ + this.javaMailSender = javaMailSender; + this.questionMapper = questionMapper; + this.adminAddress = adminAddress; + } + + public Question sendQuestion(QuestionReq.General request){ + MimeMessage mimeMessage = questionMapper.createMessage(request, adminAddress); + // TODO : 일단 DB에 저장되는 부분은 보류 + // Question question = questionMapper.createQuestion(request); + + Question question = request.toEntity(); try{ - MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); - helper.setTo(request.email()); - helper.setSubject("테스트용 이메일"); - helper.setText(request.content()); javaMailSender.send(mimeMessage); - - } catch(Exception e) { - throw new IllegalArgumentException("tset"); + return question; + } catch(Exception e){ + throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAILERROR); } } From 1353fae2c5a068a157200d0e55c6bdedcda56998 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 7 Apr 2024 16:24:30 +0900 Subject: [PATCH 07/42] =?UTF-8?q?fix:=20=EB=AC=B8=EC=9D=98=20=EB=B0=9C?= =?UTF-8?q?=EC=86=A1=20=EB=82=B4=EC=9A=A9=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apis/question/mapper/QuestionMapper.java | 18 +++++++++++++++--- .../api/config/security/SecurityConfig.java | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java index fd47df0b4..251b45645 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -18,7 +18,7 @@ public class QuestionMapper { private final QuestionService questionService; /** - * + * MimeMessageHelper 객체에 필요한 값들을 채워넣고 반환한다. */ public MimeMessage createMessage(QuestionReq.General request, String address){ MimeMessage mimeMessage = javaMailSender.createMimeMessage(); @@ -26,8 +26,8 @@ public MimeMessage createMessage(QuestionReq.General request, String address){ try{ MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); helper.setTo(address); - helper.setSubject("테스트용 이메일"); - helper.setText(request.content()); + helper.setSubject(createSubject(request)); + helper.setText(createContent(request), true); return mimeMessage; } catch(Exception e) { @@ -46,4 +46,16 @@ public Question createQuestion(QuestionReq.General request){ return response; } + private String createSubject(QuestionReq.General request){ + + return request.email() + "님께서 문의사항을 남겨 주셨어요."; + } + + private String createContent(QuestionReq.General request){ + String from = "

문의자 : " + request.email() + "

"; + String category = "

카테고리 : " + request.category().getTitle() + "


"; + String content = "문의 내용 : " + request.content(); + + return from + category + content; + } } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java index 8fd2aa71d..1699fb815 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java @@ -44,7 +44,7 @@ public SecurityFilterChain filterChainDev(HttpSecurity http) throws Exception { .authorizeHttpRequests( auth -> defaultAuthorizeHttpRequests(auth) .requestMatchers(SWAGGER_ENDPOINTS).permitAll() - .anyRequest().authenticated() + .anyRequest().permitAll() ).build(); } From f5e78d7ffae57637c0001c5bc07105369d92be5e Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 7 Apr 2024 16:24:55 +0900 Subject: [PATCH 08/42] =?UTF-8?q?feat:=20=ED=95=84=EC=9A=94=ED=95=9C=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/pennyway-app-external-api/src/main/resources/application.yml b/pennyway-app-external-api/src/main/resources/application.yml index 2d360b542..10e2368b6 100644 --- a/pennyway-app-external-api/src/main/resources/application.yml +++ b/pennyway-app-external-api/src/main/resources/application.yml @@ -4,6 +4,22 @@ spring: local: common, domain, infra dev: common, domain, infra + mail: + host: smtp.gmail.com # 1 + port: 587 # 2 + username: ${MAIL_USERNAME} + password: ${MAIL_PASSWORD} + properties: + mail: + smtp: + auth: true # 5 + timeout: 5000 # 6 + starttls: + enable: true # 7 + +app: + question-address: ${ADMIN_ADDRESS} + jwt: secret-key: access-token: ${JWT_ACCESS_SECRET_KEY} From 44258e1c22b64768818cef4444a8cae1db408a39 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 7 Apr 2024 16:46:35 +0900 Subject: [PATCH 09/42] =?UTF-8?q?docs:=20swagger=20=EB=AC=B8=EC=84=9C=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20=EB=B0=8F=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/apis/question/api/QuestionApi.java | 28 +++++++++++++++++++ .../controller/QuestionController.java | 8 ++---- 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java new file mode 100644 index 000000000..08e48f6bc --- /dev/null +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java @@ -0,0 +1,28 @@ +package kr.co.pennyway.api.apis.question.api; + +import io.lettuce.core.dynamic.annotation.Param; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.enums.ParameterIn; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.responses.ApiResponses; +import io.swagger.v3.oas.annotations.tags.Tag; +import kr.co.pennyway.api.apis.question.dto.QuestionReq; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestBody; + +@Tag(name = "[문의 API]") +public interface QuestionApi { + + @Operation(summary = "문의 전송", description = "사용자는 관리자에게 문의 메일을 발송한다.") + @Parameter(name = "email", description = "문의자 이메일") + @Parameter(name = "content", description = "문의 내용") + @Parameter(name = "category", description = "문의 카테고리" , examples = { + @ExampleObject(name = "이용 관련", value = "UTILIZATION"), @ExampleObject(name = "오류 신고", value = "BUG_REPORT"), @ExampleObject(name = "서비스 제안", value = "SUGGESTION"), @ExampleObject(name = "기타", value = "ETC") + }, required = true, in = ParameterIn.QUERY) + + ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request); +} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index 6e0ad9b14..b2c57cb17 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -1,7 +1,6 @@ package kr.co.pennyway.api.apis.question.controller; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; +import kr.co.pennyway.api.apis.question.api.QuestionApi; import kr.co.pennyway.api.apis.question.dto.QuestionReq; import kr.co.pennyway.api.apis.question.usecase.QuestionUseCase; import kr.co.pennyway.api.common.response.SuccessResponse; @@ -14,14 +13,13 @@ import org.springframework.web.bind.annotation.*; @Slf4j -@Tag(name = "[문의 API]") @RestController @RequiredArgsConstructor @RequestMapping("/v1/question") -public class QuestionController { +public class QuestionController implements QuestionApi { private final QuestionUseCase questionUseCase; - @Operation(summary = "문의 전송") + @Override @PostMapping("/send") @PreAuthorize("isAnonymous()") public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request){ From bbe30db6364413721b1590b3de7b8da27573317f Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 15:42:12 +0900 Subject: [PATCH 10/42] =?UTF-8?q?fix:=20=EB=9D=BC=EC=9D=B4=EB=B8=8C?= =?UTF-8?q?=EB=9F=AC=EB=A6=AC=20=EB=B2=84=EC=A0=84=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pennyway-app-external-api/build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennyway-app-external-api/build.gradle b/pennyway-app-external-api/build.gradle index 05182d0bc..bb4451504 100644 --- a/pennyway-app-external-api/build.gradle +++ b/pennyway-app-external-api/build.gradle @@ -29,5 +29,5 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.2.3' implementation 'org.springframework.boot:spring-boot-starter-validation:3.2.3' - implementation 'org.springframework.boot:spring-boot-starter-mail' + implementation 'org.springframework.boot:spring-boot-starter-mail:3.2.3' } From f1c01cba9d48e39eda9da2f023c2ce7109476a0b Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 16:31:50 +0900 Subject: [PATCH 11/42] =?UTF-8?q?docs:=20swagger=20parameter=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EB=B0=8F=20schema=20=EB=82=B4=EC=9A=A9=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 --- .../pennyway/api/apis/question/api/QuestionApi.java | 13 ------------- .../pennyway/api/apis/question/dto/QuestionReq.java | 7 +++---- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java index 08e48f6bc..90cecf648 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java @@ -1,13 +1,6 @@ package kr.co.pennyway.api.apis.question.api; -import io.lettuce.core.dynamic.annotation.Param; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.enums.ParameterIn; -import io.swagger.v3.oas.annotations.media.Content; -import io.swagger.v3.oas.annotations.media.ExampleObject; -import io.swagger.v3.oas.annotations.responses.ApiResponse; -import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; import kr.co.pennyway.api.apis.question.dto.QuestionReq; import org.springframework.http.ResponseEntity; @@ -18,11 +11,5 @@ public interface QuestionApi { @Operation(summary = "문의 전송", description = "사용자는 관리자에게 문의 메일을 발송한다.") - @Parameter(name = "email", description = "문의자 이메일") - @Parameter(name = "content", description = "문의 내용") - @Parameter(name = "category", description = "문의 카테고리" , examples = { - @ExampleObject(name = "이용 관련", value = "UTILIZATION"), @ExampleObject(name = "오류 신고", value = "BUG_REPORT"), @ExampleObject(name = "서비스 제안", value = "SUGGESTION"), @ExampleObject(name = "기타", value = "ETC") - }, required = true, in = ParameterIn.QUERY) - ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request); } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index a2e5ec59e..1203571a8 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -5,14 +5,13 @@ import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; public class QuestionReq { - - @Schema(name = "QuestionReqGeneral", title = "문의 요청") + @Schema(name = "QuestionReqGeneral", title = "문의 요청", allowableValues = {"UTILIZATION", "BUG_REPORT", "SUGGESTION", "ETC"}) public record General( String email, String content, QuestionCategory category - ){ - public Question toEntity(){ + ) { + public Question toEntity() { return Question.builder() .email(email) .content(content) From df0f1fb218d533e9a9cda8d7d214d7d6f8f1e844 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 16:33:32 +0900 Subject: [PATCH 12/42] =?UTF-8?q?fix:=20=EC=BB=A8=EB=B2=A4=EC=85=98?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20uri=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/apis/question/controller/QuestionController.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index b2c57cb17..76ab47bfd 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -10,19 +10,22 @@ import org.springframework.http.ResponseEntity; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.*; +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; @Slf4j @RestController @RequiredArgsConstructor -@RequestMapping("/v1/question") +@RequestMapping("/v1/questions") public class QuestionController implements QuestionApi { private final QuestionUseCase questionUseCase; @Override @PostMapping("/send") @PreAuthorize("isAnonymous()") - public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request){ + public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request) { Question question = questionUseCase.sendQuestion(request); return ResponseEntity.ok(SuccessResponse.from(question)); } From 4e1de3e7cddd59786789e603bb48193a28eb258a Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 16:37:00 +0900 Subject: [PATCH 13/42] =?UTF-8?q?fix:=20controller=20=EB=A9=94=EC=86=8C?= =?UTF-8?q?=EB=93=9C=20=EC=9D=B8=EA=B0=80=20=EA=B6=8C=ED=95=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 --- .../api/apis/question/controller/QuestionController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index 76ab47bfd..defaffa05 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -24,7 +24,7 @@ public class QuestionController implements QuestionApi { @Override @PostMapping("/send") - @PreAuthorize("isAnonymous()") + @PreAuthorize("permitAll()") public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request) { Question question = questionUseCase.sendQuestion(request); return ResponseEntity.ok(SuccessResponse.from(question)); From 59a2e665d30e02fcea22dfa5de42d55c9cbd73df Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 16:40:11 +0900 Subject: [PATCH 14/42] =?UTF-8?q?fix:=20dto=20=ED=95=84=EB=93=9C=EB=B3=84?= =?UTF-8?q?=20schema=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/pennyway/api/apis/question/dto/QuestionReq.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index 1203571a8..0ed33084b 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -1,14 +1,21 @@ package kr.co.pennyway.api.apis.question.dto; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; public class QuestionReq { @Schema(name = "QuestionReqGeneral", title = "문의 요청", allowableValues = {"UTILIZATION", "BUG_REPORT", "SUGGESTION", "ETC"}) public record General( + @Schema(description = "믄의자 이메일", example = "foobar@gmail.com") + @NotBlank(message = "이메일을 입력해주세요") String email, + @Schema(description = "문의 내용", example = "문의 내용입니다.") + @NotBlank(message = "문의 내용을 입력해주세요") String content, + @Schema(description = "문의 카테고리", example = "UTILIZATION") + @NotBlank(message = "문의 카테고리를 입력해주세요") QuestionCategory category ) { public Question toEntity() { From 1e7d533ed3b3d4e1613d9fb3b06a4e0148fdcd68 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 16:44:38 +0900 Subject: [PATCH 15/42] =?UTF-8?q?fix:=20dto=20email=20=ED=95=84=EB=93=9C?= =?UTF-8?q?=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=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 --- .../java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index 0ed33084b..77c608d19 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -1,6 +1,7 @@ package kr.co.pennyway.api.apis.question.dto; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; @@ -10,6 +11,7 @@ public class QuestionReq { public record General( @Schema(description = "믄의자 이메일", example = "foobar@gmail.com") @NotBlank(message = "이메일을 입력해주세요") + @Email(message = "이메일 형식이 올바르지 않습니다.") String email, @Schema(description = "문의 내용", example = "문의 내용입니다.") @NotBlank(message = "문의 내용을 입력해주세요") From 905cec3c73cee0f1ee4bf50e0e5537c32423f54b Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Mon, 8 Apr 2024 17:55:03 +0900 Subject: [PATCH 16/42] =?UTF-8?q?fix:=20category(enum)=20=ED=95=84?= =?UTF-8?q?=EB=93=9C=20=EC=9C=A0=ED=9A=A8=EC=84=B1=20=EA=B2=80=EC=82=AC=20?= =?UTF-8?q?=EC=B2=98=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/apis/question/dto/QuestionReq.java | 3 ++- .../api/apis/question/mapper/QuestionMapper.java | 15 +++++++++------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index 77c608d19..6beb3eb12 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -3,6 +3,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; @@ -17,7 +18,7 @@ public record General( @NotBlank(message = "문의 내용을 입력해주세요") String content, @Schema(description = "문의 카테고리", example = "UTILIZATION") - @NotBlank(message = "문의 카테고리를 입력해주세요") + @NotNull(message = "문의 카테고리를 입력해주세요") QuestionCategory category ) { public Question toEntity() { diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java index 251b45645..f232991df 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -8,11 +8,13 @@ import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; import kr.co.pennyway.domain.domains.question.service.QuestionService; import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; @Mapper @AllArgsConstructor +@Slf4j public class QuestionMapper { private final JavaMailSender javaMailSender; private final QuestionService questionService; @@ -20,17 +22,18 @@ public class QuestionMapper { /** * MimeMessageHelper 객체에 필요한 값들을 채워넣고 반환한다. */ - public MimeMessage createMessage(QuestionReq.General request, String address){ + public MimeMessage createMessage(QuestionReq.General request, String address) { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); - try{ + try { MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); helper.setTo(address); helper.setSubject(createSubject(request)); helper.setText(createContent(request), true); return mimeMessage; - } catch(Exception e) { + } catch (Exception e) { + log.warn(e.getMessage()); throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAILERROR); } @@ -39,19 +42,19 @@ public MimeMessage createMessage(QuestionReq.General request, String address){ /** * Question 객체를 생성해 반환하며, DB에 저장한다. */ - public Question createQuestion(QuestionReq.General request){ + public Question createQuestion(QuestionReq.General request) { Question question = request.toEntity(); Question response = questionService.createQuestion(question); return response; } - private String createSubject(QuestionReq.General request){ + private String createSubject(QuestionReq.General request) { return request.email() + "님께서 문의사항을 남겨 주셨어요."; } - private String createContent(QuestionReq.General request){ + private String createContent(QuestionReq.General request) { String from = "

문의자 : " + request.email() + "

"; String category = "

카테고리 : " + request.category().getTitle() + "


"; String content = "문의 내용 : " + request.content(); From 120c5ded2c3c30f9944290f5224ec476037a04e2 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Wed, 10 Apr 2024 01:26:31 +0900 Subject: [PATCH 17/42] =?UTF-8?q?fix:=20restful=20=EC=9B=90=EC=B9=99?= =?UTF-8?q?=EC=97=90=20=EB=94=B0=EB=A5=B8=20request=20uri=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 --- .../api/apis/question/controller/QuestionController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index defaffa05..ba1003475 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -23,7 +23,7 @@ public class QuestionController implements QuestionApi { private final QuestionUseCase questionUseCase; @Override - @PostMapping("/send") + @PostMapping("") @PreAuthorize("permitAll()") public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request) { Question question = questionUseCase.sendQuestion(request); From 57d8595b70e0cf2590e56013f556b967b50ee081 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Wed, 10 Apr 2024 02:02:51 +0900 Subject: [PATCH 18/42] =?UTF-8?q?fix:=20dto=20inner=20class=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 --- .../kr/co/pennyway/api/apis/question/api/QuestionApi.java | 4 +++- .../api/apis/question/controller/QuestionController.java | 2 +- .../kr/co/pennyway/api/apis/question/dto/QuestionReq.java | 8 +++----- .../pennyway/api/apis/question/mapper/QuestionMapper.java | 8 ++++---- .../api/apis/question/usecase/QuestionUseCase.java | 2 +- .../domain/domains/question/domain/QuestionCategory.java | 5 ----- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java index 90cecf648..676cefc03 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java @@ -1,6 +1,7 @@ package kr.co.pennyway.api.apis.question.api; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import kr.co.pennyway.api.apis.question.dto.QuestionReq; import org.springframework.http.ResponseEntity; @@ -11,5 +12,6 @@ public interface QuestionApi { @Operation(summary = "문의 전송", description = "사용자는 관리자에게 문의 메일을 발송한다.") - ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request); + @Schema(name = "QuestionReqGeneral", title = "문의 요청", allowableValues = {"UTILIZATION", "BUG_REPORT", "SUGGESTION", "ETC"}) + ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq request); } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index ba1003475..00632a46c 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -25,7 +25,7 @@ public class QuestionController implements QuestionApi { @Override @PostMapping("") @PreAuthorize("permitAll()") - public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq.General request) { + public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq request) { Question question = questionUseCase.sendQuestion(request); return ResponseEntity.ok(SuccessResponse.from(question)); } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index 6beb3eb12..fe27d0cff 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -7,9 +7,7 @@ import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; -public class QuestionReq { - @Schema(name = "QuestionReqGeneral", title = "문의 요청", allowableValues = {"UTILIZATION", "BUG_REPORT", "SUGGESTION", "ETC"}) - public record General( +public record QuestionReq ( @Schema(description = "믄의자 이메일", example = "foobar@gmail.com") @NotBlank(message = "이메일을 입력해주세요") @Email(message = "이메일 형식이 올바르지 않습니다.") @@ -20,7 +18,7 @@ public record General( @Schema(description = "문의 카테고리", example = "UTILIZATION") @NotNull(message = "문의 카테고리를 입력해주세요") QuestionCategory category - ) { + ){ public Question toEntity() { return Question.builder() .email(email) @@ -29,4 +27,4 @@ public Question toEntity() { .build(); } } -} + diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java index f232991df..96f1bdda8 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -22,7 +22,7 @@ public class QuestionMapper { /** * MimeMessageHelper 객체에 필요한 값들을 채워넣고 반환한다. */ - public MimeMessage createMessage(QuestionReq.General request, String address) { + public MimeMessage createMessage(QuestionReq request, String address) { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); try { @@ -42,19 +42,19 @@ public MimeMessage createMessage(QuestionReq.General request, String address) { /** * Question 객체를 생성해 반환하며, DB에 저장한다. */ - public Question createQuestion(QuestionReq.General request) { + public Question createQuestion(QuestionReq request) { Question question = request.toEntity(); Question response = questionService.createQuestion(question); return response; } - private String createSubject(QuestionReq.General request) { + private String createSubject(QuestionReq request) { return request.email() + "님께서 문의사항을 남겨 주셨어요."; } - private String createContent(QuestionReq.General request) { + private String createContent(QuestionReq request) { String from = "

문의자 : " + request.email() + "

"; String category = "

카테고리 : " + request.category().getTitle() + "


"; String content = "문의 내용 : " + request.content(); diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index 74f9a22a3..88deb5e6b 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -27,7 +27,7 @@ public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMap this.adminAddress = adminAddress; } - public Question sendQuestion(QuestionReq.General request){ + public Question sendQuestion(QuestionReq request){ MimeMessage mimeMessage = questionMapper.createMessage(request, adminAddress); // TODO : 일단 DB에 저장되는 부분은 보류 // Question question = questionMapper.createQuestion(request); diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java index a79e972c1..3f3ce16f6 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java @@ -4,11 +4,6 @@ import lombok.Getter; import lombok.RequiredArgsConstructor; -/** - * 문의 요청 DTO - *
- * 문의 요청시 사용됩니다. - */ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter From 248fc8558350eb568b5b5052eb8d6028b0bae7b2 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Wed, 10 Apr 2024 02:04:04 +0900 Subject: [PATCH 19/42] =?UTF-8?q?fix:=20transactional=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domain/domains/question/service/QuestionService.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java index 515ac4cd8..493242d84 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java @@ -1,12 +1,12 @@ package kr.co.pennyway.domain.domains.question.service; -import jakarta.transaction.Transactional; +import kr.co.pennyway.common.annotation.DomainService; import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.repository.QuestionRepository; import lombok.RequiredArgsConstructor; -import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; -@Service +@DomainService @RequiredArgsConstructor public class QuestionService { private final QuestionRepository questionRepository; From a1fc83690bbf6b49acb76ccbd4baa40486c590ea Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 10 Apr 2024 15:20:41 +0900 Subject: [PATCH 20/42] =?UTF-8?q?fix:=20email=5Ferror=20=EC=98=A4=ED=83=88?= =?UTF-8?q?=EC=9E=90=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/apis/question/mapper/QuestionMapper.java | 2 +- .../apis/question/usecase/QuestionUseCase.java | 15 ++++++--------- .../question/exception/QuestionErrorCode.java | 2 +- 3 files changed, 8 insertions(+), 11 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java index 96f1bdda8..312223b37 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -34,7 +34,7 @@ public MimeMessage createMessage(QuestionReq request, String address) { return mimeMessage; } catch (Exception e) { log.warn(e.getMessage()); - throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAILERROR); + throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAIL_ERROR); } } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index 88deb5e6b..001255ed0 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -1,18 +1,15 @@ package kr.co.pennyway.api.apis.question.usecase; +import jakarta.mail.internet.MimeMessage; import kr.co.pennyway.api.apis.question.dto.QuestionReq; import kr.co.pennyway.api.apis.question.mapper.QuestionMapper; import kr.co.pennyway.common.annotation.UseCase; import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.exception.QuestionErrorCode; import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; -import lombok.AllArgsConstructor; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import jakarta.mail.internet.MimeMessage; import org.springframework.beans.factory.annotation.Value; import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; @Slf4j @UseCase @@ -21,24 +18,24 @@ public class QuestionUseCase { private final QuestionMapper questionMapper; private String adminAddress; - public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMapper, @Value("${app.question-address}") String adminAddress){ + public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMapper, @Value("${app.question-address}") String adminAddress) { this.javaMailSender = javaMailSender; this.questionMapper = questionMapper; this.adminAddress = adminAddress; } - public Question sendQuestion(QuestionReq request){ + public Question sendQuestion(QuestionReq request) { MimeMessage mimeMessage = questionMapper.createMessage(request, adminAddress); // TODO : 일단 DB에 저장되는 부분은 보류 // Question question = questionMapper.createQuestion(request); Question question = request.toEntity(); - try{ + try { javaMailSender.send(mimeMessage); return question; - } catch(Exception e){ - throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAILERROR); + } catch (Exception e) { + throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAIL_ERROR); } } diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java index c041d3760..6b20844a1 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/exception/QuestionErrorCode.java @@ -8,7 +8,7 @@ @AllArgsConstructor public enum QuestionErrorCode implements BaseErrorCode { - INTERNAL_MAILERROR(StatusCode.INTERNAL_SERVER_ERROR, ReasonCode.UNEXPECTED_ERROR, "메일 발송에 실패했습니다."); + INTERNAL_MAIL_ERROR(StatusCode.INTERNAL_SERVER_ERROR, ReasonCode.UNEXPECTED_ERROR, "메일 발송에 실패했습니다."); private final StatusCode statusCode; private final ReasonCode reasonCode; From 02f541715d528fd2d185f4acf2b897928d761b77 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 10 Apr 2024 15:30:47 +0900 Subject: [PATCH 21/42] =?UTF-8?q?fix:=20=EA=B3=B5=ED=86=B5=20=ED=97=88?= =?UTF-8?q?=EC=9A=A9=20endpoint=20=EC=84=A0=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/pennyway/api/config/security/SecurityConfig.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java index 1699fb815..ffa2bd386 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/config/security/SecurityConfig.java @@ -27,9 +27,11 @@ @RequiredArgsConstructor public class SecurityConfig { private static final String[] READ_ONLY_PUBLIC_ENDPOINTS = {"/favicon.ico", "/v1/duplicate/**"}; + private static final String[] PUBLIC_ENDPOINTS = {"/v1/questions/**"}; private static final String[] ANONYMOUS_ENDPOINTS = {"/v1/auth/**"}; private static final String[] SWAGGER_ENDPOINTS = {"/api-docs/**", "/v3/api-docs/**", "/swagger-ui/**", "/swagger",}; + private final SecurityAdapterConfig securityAdapterConfig; private final CorsConfigurationSource corsConfigurationSource; private final AccessDeniedHandler accessDeniedHandler; @@ -44,7 +46,7 @@ public SecurityFilterChain filterChainDev(HttpSecurity http) throws Exception { .authorizeHttpRequests( auth -> defaultAuthorizeHttpRequests(auth) .requestMatchers(SWAGGER_ENDPOINTS).permitAll() - .anyRequest().permitAll() + .anyRequest().authenticated() ).build(); } @@ -79,6 +81,7 @@ private AbstractRequestMatcherRegistry Date: Wed, 10 Apr 2024 19:11:59 +0900 Subject: [PATCH 22/42] =?UTF-8?q?fix:=20createddate=20=EB=A5=BC=20?= =?UTF-8?q?=EC=82=AC=EC=9A=A9=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20ent?= =?UTF-8?q?itylistners=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/apis/question/dto/QuestionReq.java | 38 +++++++++---------- .../domains/question/domain/Question.java | 10 +---- 2 files changed, 21 insertions(+), 27 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index fe27d0cff..9b31fa91f 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -7,24 +7,24 @@ import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; -public record QuestionReq ( - @Schema(description = "믄의자 이메일", example = "foobar@gmail.com") - @NotBlank(message = "이메일을 입력해주세요") - @Email(message = "이메일 형식이 올바르지 않습니다.") - String email, - @Schema(description = "문의 내용", example = "문의 내용입니다.") - @NotBlank(message = "문의 내용을 입력해주세요") - String content, - @Schema(description = "문의 카테고리", example = "UTILIZATION") - @NotNull(message = "문의 카테고리를 입력해주세요") - QuestionCategory category - ){ - public Question toEntity() { - return Question.builder() - .email(email) - .content(content) - .category(category) - .build(); - } +public record QuestionReq( + @Schema(description = "믄의자 이메일", example = "foobar@gmail.com") + @NotBlank(message = "이메일을 입력해주세요") + @Email(message = "이메일 형식이 올바르지 않습니다.") + String email, + @Schema(description = "문의 내용", example = "문의 내용입니다.") + @NotBlank(message = "문의 내용을 입력해주세요") + String content, + @Schema(description = "문의 카테고리", example = "UTILIZATION") + @NotNull(message = "문의 카테고리를 입력해주세요") + QuestionCategory category +) { + public Question toEntity() { + return Question.builder() + .email(email) + .content(content) + .category(category) + .build(); } +} diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java index 28dc87bf7..502a0d588 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java @@ -1,13 +1,12 @@ package kr.co.pennyway.domain.domains.question.domain; import jakarta.persistence.*; -import kr.co.pennyway.domain.domains.user.domain.User; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; -import org.hibernate.annotations.ColumnDefault; import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.jpa.domain.support.AuditingEntityListener; import java.time.LocalDateTime; @@ -15,22 +14,18 @@ @Getter @Table(name = "Question") @NoArgsConstructor(access = AccessLevel.PROTECTED) +@EntityListeners(AuditingEntityListener.class) public class Question { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; - private String email; - private QuestionCategory category; private String content; - - @CreatedDate @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; - @ColumnDefault("NULL") private LocalDateTime deletedAt; @Builder @@ -39,6 +34,5 @@ private Question(String email, QuestionCategory category, String content, LocalD this.category = category; this.content = content; this.createdAt = createdAt; - this.deletedAt = deletedAt; } } From 47d866cb494f79f84ebf9d287b0a5e71deb0e81e Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 10 Apr 2024 19:12:20 +0900 Subject: [PATCH 23/42] =?UTF-8?q?fix:=20domainservice=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pennyway/api/apis/question/usecase/QuestionUseCase.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index 001255ed0..dc1e05c14 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -26,10 +26,7 @@ public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMap public Question sendQuestion(QuestionReq request) { MimeMessage mimeMessage = questionMapper.createMessage(request, adminAddress); - // TODO : 일단 DB에 저장되는 부분은 보류 - // Question question = questionMapper.createQuestion(request); - - Question question = request.toEntity(); + Question question = questionMapper.createQuestion(request); try { javaMailSender.send(mimeMessage); From 2677d4593266797c493da66d78d7eb069f27ad54 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 10 Apr 2024 19:26:58 +0900 Subject: [PATCH 24/42] =?UTF-8?q?fix:=20swagger=20schema=20=EC=98=A4?= =?UTF-8?q?=ED=83=88=EC=9E=90=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20enum=20?= =?UTF-8?q?=EC=84=A4=EB=AA=85=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/pennyway/api/apis/question/api/QuestionApi.java | 2 +- .../java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java index 676cefc03..029280886 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java @@ -12,6 +12,6 @@ public interface QuestionApi { @Operation(summary = "문의 전송", description = "사용자는 관리자에게 문의 메일을 발송한다.") - @Schema(name = "QuestionReqGeneral", title = "문의 요청", allowableValues = {"UTILIZATION", "BUG_REPORT", "SUGGESTION", "ETC"}) + @Schema(name = "QuestionReqGeneral", title = "문의 요청") ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq request); } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index 9b31fa91f..984a908eb 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -8,7 +8,7 @@ import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; public record QuestionReq( - @Schema(description = "믄의자 이메일", example = "foobar@gmail.com") + @Schema(description = "문의자 이메일", example = "foobar@gmail.com") @NotBlank(message = "이메일을 입력해주세요") @Email(message = "이메일 형식이 올바르지 않습니다.") String email, From c6d1eb8774f009e1b31920f42038218b9c96f50b Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 10 Apr 2024 19:39:03 +0900 Subject: [PATCH 25/42] =?UTF-8?q?fix:=20transactional=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java index 312223b37..e3d08244e 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -11,6 +11,7 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.mail.javamail.JavaMailSender; import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.transaction.annotation.Transactional; @Mapper @AllArgsConstructor @@ -42,6 +43,7 @@ public MimeMessage createMessage(QuestionReq request, String address) { /** * Question 객체를 생성해 반환하며, DB에 저장한다. */ + @Transactional public Question createQuestion(QuestionReq request) { Question question = request.toEntity(); Question response = questionService.createQuestion(question); From fc9a3dbdac856c4cb9e2e46b1a5d272c31d2ba70 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 14 Apr 2024 02:40:28 +0900 Subject: [PATCH 26/42] =?UTF-8?q?fix:=20@schema=20=EC=96=B4=EB=85=B8?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EC=85=98=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/kr/co/pennyway/api/apis/question/api/QuestionApi.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java index 029280886..e2ffb5518 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java @@ -1,7 +1,6 @@ package kr.co.pennyway.api.apis.question.api; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.tags.Tag; import kr.co.pennyway.api.apis.question.dto.QuestionReq; import org.springframework.http.ResponseEntity; @@ -12,6 +11,5 @@ public interface QuestionApi { @Operation(summary = "문의 전송", description = "사용자는 관리자에게 문의 메일을 발송한다.") - @Schema(name = "QuestionReqGeneral", title = "문의 요청") ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq request); } From 19e22aaa538122d0811297de4cd568eb6c98c858 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 14 Apr 2024 02:41:06 +0900 Subject: [PATCH 27/42] =?UTF-8?q?fix:=20questioncategory=20enum=20converte?= =?UTF-8?q?r=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/apis/question/dto/QuestionReq.java | 3 +-- .../converter/QuestionCategoryConverter.java | 13 +++++++++++++ .../domains/question/domain/Question.java | 5 ++++- .../question/domain/QuestionCategory.java | 17 ++++++++++++----- 4 files changed, 30 insertions(+), 8 deletions(-) create mode 100644 pennyway-domain/src/main/java/kr/co/pennyway/domain/common/converter/QuestionCategoryConverter.java diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java index 984a908eb..78c0fd41b 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/dto/QuestionReq.java @@ -26,5 +26,4 @@ public Question toEntity() { .category(category) .build(); } -} - +} \ No newline at end of file diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/common/converter/QuestionCategoryConverter.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/common/converter/QuestionCategoryConverter.java new file mode 100644 index 000000000..d40a102f3 --- /dev/null +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/common/converter/QuestionCategoryConverter.java @@ -0,0 +1,13 @@ +package kr.co.pennyway.domain.common.converter; + +import jakarta.persistence.Converter; +import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; + +@Converter +public class QuestionCategoryConverter extends AbstractLegacyEnumAttributeConverter { + private static final String ENUM_NAME = "문의 카테고리"; + + public QuestionCategoryConverter() { + super(QuestionCategory.class, false, ENUM_NAME); + } +} \ No newline at end of file diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java index 502a0d588..f9b57ad2b 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/Question.java @@ -1,6 +1,7 @@ package kr.co.pennyway.domain.domains.question.domain; import jakarta.persistence.*; +import kr.co.pennyway.domain.common.converter.QuestionCategoryConverter; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -19,13 +20,15 @@ public class Question { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; + @Column(nullable = false) private String email; + @Convert(converter = QuestionCategoryConverter.class) + @Column(nullable = false) private QuestionCategory category; private String content; @CreatedDate @Column(name = "created_at", nullable = false, updatable = false) private LocalDateTime createdAt; - private LocalDateTime deletedAt; @Builder diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java index 3f3ce16f6..f47a242cd 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java @@ -1,5 +1,6 @@ package kr.co.pennyway.domain.domains.question.domain; +import kr.co.pennyway.domain.common.converter.LegacyCommonType; import lombok.AccessLevel; import lombok.Getter; import lombok.RequiredArgsConstructor; @@ -7,11 +8,17 @@ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter -public enum QuestionCategory { - UTILIZATION("이용 관련"), - BUG_REPORT("오류 신고"), - SUGGESTION("서비스 제안"), - ETC("기타"); +public enum QuestionCategory implements LegacyCommonType { + UTILIZATION("1","이용 관련"), + BUG_REPORT("2","오류 신고"), + SUGGESTION("3","서비스 제안"), + ETC("4","기타"); + private final String code; private final String title; + + @Override + public String getCode(){ + return code; + } } From 2f0bb95e1bf90d847a03b4dd660885e5643673f6 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Sun, 14 Apr 2024 02:50:48 +0900 Subject: [PATCH 28/42] =?UTF-8?q?fix:=20sendquestion=20=EC=9D=91=EB=8B=B5?= =?UTF-8?q?=20nocontent=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 --- .../api/apis/question/controller/QuestionController.java | 5 ++--- .../pennyway/api/apis/question/mapper/QuestionMapper.java | 6 ++---- .../pennyway/api/apis/question/usecase/QuestionUseCase.java | 6 ++---- .../domain/domains/question/service/QuestionService.java | 4 +++- 4 files changed, 9 insertions(+), 12 deletions(-) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java index 00632a46c..3cdba1f12 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/controller/QuestionController.java @@ -4,7 +4,6 @@ import kr.co.pennyway.api.apis.question.dto.QuestionReq; import kr.co.pennyway.api.apis.question.usecase.QuestionUseCase; import kr.co.pennyway.api.common.response.SuccessResponse; -import kr.co.pennyway.domain.domains.question.domain.Question; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.http.ResponseEntity; @@ -26,7 +25,7 @@ public class QuestionController implements QuestionApi { @PostMapping("") @PreAuthorize("permitAll()") public ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq request) { - Question question = questionUseCase.sendQuestion(request); - return ResponseEntity.ok(SuccessResponse.from(question)); + questionUseCase.sendQuestion(request); + return ResponseEntity.ok(SuccessResponse.noContent()); } } diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java index e3d08244e..560501ce3 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java @@ -44,11 +44,9 @@ public MimeMessage createMessage(QuestionReq request, String address) { * Question 객체를 생성해 반환하며, DB에 저장한다. */ @Transactional - public Question createQuestion(QuestionReq request) { + public void createQuestion(QuestionReq request) { Question question = request.toEntity(); - Question response = questionService.createQuestion(question); - - return response; + questionService.createQuestion(question); } private String createSubject(QuestionReq request) { diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index dc1e05c14..e17e8bea9 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -4,7 +4,6 @@ import kr.co.pennyway.api.apis.question.dto.QuestionReq; import kr.co.pennyway.api.apis.question.mapper.QuestionMapper; import kr.co.pennyway.common.annotation.UseCase; -import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.exception.QuestionErrorCode; import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; import lombok.extern.slf4j.Slf4j; @@ -24,13 +23,12 @@ public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMap this.adminAddress = adminAddress; } - public Question sendQuestion(QuestionReq request) { + public void sendQuestion(QuestionReq request) { MimeMessage mimeMessage = questionMapper.createMessage(request, adminAddress); - Question question = questionMapper.createQuestion(request); + questionMapper.createQuestion(request); try { javaMailSender.send(mimeMessage); - return question; } catch (Exception e) { throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAIL_ERROR); } diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java index 493242d84..a8e68ce4d 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/service/QuestionService.java @@ -12,6 +12,8 @@ public class QuestionService { private final QuestionRepository questionRepository; @Transactional - public Question createQuestion(Question question) { return questionRepository.save(question);} + public void createQuestion(Question question) { + questionRepository.save(question); + } } From 014f8750dc10892a2430eecbc0cc8c1c3ce2c806 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Tue, 16 Apr 2024 04:09:48 +0900 Subject: [PATCH 29/42] =?UTF-8?q?refactor:=20starter-mail=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pennyway-app-external-api/build.gradle | 1 - pennyway-infra/build.gradle | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/pennyway-app-external-api/build.gradle b/pennyway-app-external-api/build.gradle index bb4451504..2ae563a35 100644 --- a/pennyway-app-external-api/build.gradle +++ b/pennyway-app-external-api/build.gradle @@ -29,5 +29,4 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-web:3.2.3' implementation 'org.springframework.boot:spring-boot-starter-validation:3.2.3' - implementation 'org.springframework.boot:spring-boot-starter-mail:3.2.3' } diff --git a/pennyway-infra/build.gradle b/pennyway-infra/build.gradle index a214aa707..90f04ad9e 100644 --- a/pennyway-infra/build.gradle +++ b/pennyway-infra/build.gradle @@ -21,4 +21,7 @@ dependencies { implementation platform("org.springframework.cloud:spring-cloud-dependencies:2023.0.1") implementation 'org.springframework.cloud:spring-cloud-starter-openfeign:4.1.1' implementation 'io.github.openfeign:feign-okhttp:13.2' + + /* mail */ + implementation 'org.springframework.boot:spring-boot-starter-mail:3.2.3' } From d584a89405561a76bec5447b490f384cd3452cfb Mon Sep 17 00:00:00 2001 From: asn6878 Date: Tue, 16 Apr 2024 04:12:50 +0900 Subject: [PATCH 30/42] =?UTF-8?q?refactor:=20starter-mail=20=EC=9D=98?= =?UTF-8?q?=EC=A1=B4=EC=84=B1=20=EA=B5=AC=EC=84=B1=20=EC=86=8D=EC=84=B1=20?= =?UTF-8?q?=EB=B3=80=EC=88=98=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 16 ---------------- .../src/main/resources/application-infra.yml | 17 +++++++++++++++++ 2 files changed, 17 insertions(+), 16 deletions(-) diff --git a/pennyway-app-external-api/src/main/resources/application.yml b/pennyway-app-external-api/src/main/resources/application.yml index 10e2368b6..2d360b542 100644 --- a/pennyway-app-external-api/src/main/resources/application.yml +++ b/pennyway-app-external-api/src/main/resources/application.yml @@ -4,22 +4,6 @@ spring: local: common, domain, infra dev: common, domain, infra - mail: - host: smtp.gmail.com # 1 - port: 587 # 2 - username: ${MAIL_USERNAME} - password: ${MAIL_PASSWORD} - properties: - mail: - smtp: - auth: true # 5 - timeout: 5000 # 6 - starttls: - enable: true # 7 - -app: - question-address: ${ADMIN_ADDRESS} - jwt: secret-key: access-token: ${JWT_ACCESS_SECRET_KEY} diff --git a/pennyway-infra/src/main/resources/application-infra.yml b/pennyway-infra/src/main/resources/application-infra.yml index e0ff311d1..58ca644b4 100644 --- a/pennyway-infra/src/main/resources/application-infra.yml +++ b/pennyway-infra/src/main/resources/application-infra.yml @@ -9,6 +9,23 @@ spring: port: ${REDIS_PORT} password: ${REDIS_PASSWORD} + mail: + host: smtp.gmail.com # 1 + port: 587 # 2 + username: ${MAIL_USERNAME} + password: ${MAIL_PASSWORD} + properties: + mail: + smtp: + auth: true # 5 + timeout: 5000 # 6 + starttls: + enable: true # 7 + +app: + question-address: ${ADMIN_ADDRESS} + + pennyway: server: domain: From 7ad53cc550ad5c48fb9fe562fa665d6bb0305e77 Mon Sep 17 00:00:00 2001 From: asn6878 Date: Tue, 16 Apr 2024 18:02:54 +0900 Subject: [PATCH 31/42] =?UTF-8?q?refactor:=20=EB=A9=94=EC=9D=BC=EB=B0=9C?= =?UTF-8?q?=EC=86=A1=20=EB=A1=9C=EC=A7=81=20infra=20=EB=AA=A8=EB=93=88=20?= =?UTF-8?q?=EC=9D=B4=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../apis/question/mapper/QuestionMapper.java | 64 ------------------- .../question/usecase/QuestionUseCase.java | 36 ++++------- .../client/google/mail/GoogleMailSender.java | 50 +++++++++++++++ 3 files changed, 63 insertions(+), 87 deletions(-) delete mode 100644 pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java create mode 100644 pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java deleted file mode 100644 index 560501ce3..000000000 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/mapper/QuestionMapper.java +++ /dev/null @@ -1,64 +0,0 @@ -package kr.co.pennyway.api.apis.question.mapper; - -import jakarta.mail.internet.MimeMessage; -import kr.co.pennyway.api.apis.question.dto.QuestionReq; -import kr.co.pennyway.common.annotation.Mapper; -import kr.co.pennyway.domain.domains.question.domain.Question; -import kr.co.pennyway.domain.domains.question.exception.QuestionErrorCode; -import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; -import kr.co.pennyway.domain.domains.question.service.QuestionService; -import lombok.AllArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.transaction.annotation.Transactional; - -@Mapper -@AllArgsConstructor -@Slf4j -public class QuestionMapper { - private final JavaMailSender javaMailSender; - private final QuestionService questionService; - - /** - * MimeMessageHelper 객체에 필요한 값들을 채워넣고 반환한다. - */ - public MimeMessage createMessage(QuestionReq request, String address) { - MimeMessage mimeMessage = javaMailSender.createMimeMessage(); - - try { - MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); - helper.setTo(address); - helper.setSubject(createSubject(request)); - helper.setText(createContent(request), true); - - return mimeMessage; - } catch (Exception e) { - log.warn(e.getMessage()); - throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAIL_ERROR); - } - - } - - /** - * Question 객체를 생성해 반환하며, DB에 저장한다. - */ - @Transactional - public void createQuestion(QuestionReq request) { - Question question = request.toEntity(); - questionService.createQuestion(question); - } - - private String createSubject(QuestionReq request) { - - return request.email() + "님께서 문의사항을 남겨 주셨어요."; - } - - private String createContent(QuestionReq request) { - String from = "

문의자 : " + request.email() + "

"; - String category = "

카테고리 : " + request.category().getTitle() + "


"; - String content = "문의 내용 : " + request.content(); - - return from + category + content; - } -} diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index e17e8bea9..43485e35f 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -1,37 +1,27 @@ package kr.co.pennyway.api.apis.question.usecase; -import jakarta.mail.internet.MimeMessage; +import jakarta.transaction.Transactional; import kr.co.pennyway.api.apis.question.dto.QuestionReq; -import kr.co.pennyway.api.apis.question.mapper.QuestionMapper; import kr.co.pennyway.common.annotation.UseCase; -import kr.co.pennyway.domain.domains.question.exception.QuestionErrorCode; -import kr.co.pennyway.domain.domains.question.exception.QuestionErrorException; +import kr.co.pennyway.domain.domains.question.domain.Question; +import kr.co.pennyway.domain.domains.question.service.QuestionService; +import kr.co.pennyway.infra.client.google.mail.GoogleMailSender; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.mail.javamail.JavaMailSender; @Slf4j @UseCase +@AllArgsConstructor public class QuestionUseCase { - private final JavaMailSender javaMailSender; - private final QuestionMapper questionMapper; - private String adminAddress; - - public QuestionUseCase(JavaMailSender javaMailSender, QuestionMapper questionMapper, @Value("${app.question-address}") String adminAddress) { - this.javaMailSender = javaMailSender; - this.questionMapper = questionMapper; - this.adminAddress = adminAddress; - } + private final QuestionService questionService; + private final GoogleMailSender googleMailSender; + @Transactional public void sendQuestion(QuestionReq request) { - MimeMessage mimeMessage = questionMapper.createMessage(request, adminAddress); - questionMapper.createQuestion(request); - - try { - javaMailSender.send(mimeMessage); - } catch (Exception e) { - throw new QuestionErrorException(QuestionErrorCode.INTERNAL_MAIL_ERROR); - } + Question question = request.toEntity(); + questionService.createQuestion(question); + googleMailSender.sendMail(request.email(), request.content(), request.category().getTitle()); + // TODO : sendMail 메소드 이벤트 처리 } } diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java new file mode 100644 index 000000000..dd5655c28 --- /dev/null +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java @@ -0,0 +1,50 @@ +package kr.co.pennyway.infra.client.google.mail; + +import jakarta.mail.internet.MimeMessage; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +@Slf4j +@Component +public class GoogleMailSender { + private final JavaMailSender javaMailSender; + private final String adminAddress; + + GoogleMailSender(JavaMailSender javaMailSender, @Value("${app.question-address}") String adminAddress) { + this.javaMailSender = javaMailSender; + this.adminAddress = adminAddress; + } + + public void sendMail(String email, String content, String category) { + log.info("야 이까지 잘실행된다야"); + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + + try { + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, false, "UTF-8"); + helper.setTo(adminAddress); + helper.setSubject(createSubject(email)); + helper.setText(createContent(email, content, category), true); + + javaMailSender.send(mimeMessage); + } catch (Exception e) { + log.warn(e.getMessage()); + + throw new IllegalArgumentException(e.getMessage()); + } + } + + private String createSubject(String email) { + return email + "님께서 문의사항을 남겨 주셨어요."; + } + + private String createContent(String email, String content, String category) { + String fromField = "

문의자 : " + email + "

"; + String categoryField = "

카테고리 : " + category + "


"; + String contentField = "문의 내용 : " + content; + + return fromField + categoryField + contentField; + } +} From 3412ba8ac4ac662e6402dc5a7837de07293559d0 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Tue, 16 Apr 2024 19:12:38 +0900 Subject: [PATCH 32/42] =?UTF-8?q?fix:=20=EC=9E=84=EC=8B=9C=20=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../co/pennyway/infra/client/google/mail/GoogleMailSender.java | 1 - 1 file changed, 1 deletion(-) diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java index dd5655c28..797bcce32 100644 --- a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java @@ -19,7 +19,6 @@ public class GoogleMailSender { } public void sendMail(String email, String content, String category) { - log.info("야 이까지 잘실행된다야"); MimeMessage mimeMessage = javaMailSender.createMimeMessage(); try { From 20413404362868e16db2455db1e7d62cdb036b62 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 17 Apr 2024 13:24:43 +0900 Subject: [PATCH 33/42] =?UTF-8?q?refactor:=20=EC=9D=98=EC=A1=B4=EC=84=B1?= =?UTF-8?q?=20=EC=A3=BC=EC=9E=85=EC=9D=84=20=EC=9C=84=ED=95=9C=20mailconfi?= =?UTF-8?q?g=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../co/pennyway/infra/config/MailConfig.java | 46 +++++++++++++++++++ .../src/main/resources/application-infra.yml | 17 ++----- 2 files changed, 50 insertions(+), 13 deletions(-) create mode 100644 pennyway-infra/src/main/java/kr/co/pennyway/infra/config/MailConfig.java diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/config/MailConfig.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/config/MailConfig.java new file mode 100644 index 000000000..57d0a7dcd --- /dev/null +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/config/MailConfig.java @@ -0,0 +1,46 @@ +package kr.co.pennyway.infra.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +import java.util.Properties; + +@Configuration +public class MailConfig { + @Value("${app.mail.host}") + private String host; + @Value("${app.mail.port}") + private int port; + @Value("${app.mail.username}") + private String username; + @Value("${app.mail.password}") + private String password; + + + @Bean + public JavaMailSender javaMailService() { + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + + javaMailSender.setHost(host); + javaMailSender.setPort(port); + javaMailSender.setUsername(username); + javaMailSender.setPassword(password); + javaMailSender.setJavaMailProperties(getMailProperties()); + + return javaMailSender; + } + + private Properties getMailProperties() { + Properties properties = new Properties(); + properties.setProperty("mail.transport.protocol", "smtp"); + properties.setProperty("mail.debug", "false"); + properties.setProperty("mail.smtp.auth", "true"); + properties.setProperty("mail.smtp.starttls.enable", "true"); + properties.setProperty("mail.smtp.timeout", "5000"); + + return properties; + } +} diff --git a/pennyway-infra/src/main/resources/application-infra.yml b/pennyway-infra/src/main/resources/application-infra.yml index 58ca644b4..7caa480f2 100644 --- a/pennyway-infra/src/main/resources/application-infra.yml +++ b/pennyway-infra/src/main/resources/application-infra.yml @@ -9,22 +9,13 @@ spring: port: ${REDIS_PORT} password: ${REDIS_PASSWORD} +app: + question-address: ${ADMIN_ADDRESS} mail: - host: smtp.gmail.com # 1 - port: 587 # 2 + host: smtp.gmail.com + port: 587 username: ${MAIL_USERNAME} password: ${MAIL_PASSWORD} - properties: - mail: - smtp: - auth: true # 5 - timeout: 5000 # 6 - starttls: - enable: true # 7 - -app: - question-address: ${ADMIN_ADDRESS} - pennyway: server: From 646b3d246743a04979d0bb9d79810f3354cc5fd0 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Wed, 17 Apr 2024 14:31:53 +0900 Subject: [PATCH 34/42] =?UTF-8?q?refactor:=20transactionaleventlistener?= =?UTF-8?q?=EB=A5=BC=20=ED=99=9C=EC=9A=A9=ED=95=9C=20=EB=A9=94=EC=9D=BC?= =?UTF-8?q?=EB=B0=9C=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=EC=B2=98?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../question/usecase/QuestionUseCase.java | 8 +++--- .../client/google/mail/GoogleMailSender.java | 2 +- .../infra/common/event/MailEvent.java | 11 ++++++++ .../infra/common/event/MailEventHandling.java | 28 +++++++++++++++++++ 4 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEvent.java create mode 100644 pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java index 43485e35f..3eb2ca101 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/usecase/QuestionUseCase.java @@ -5,23 +5,23 @@ import kr.co.pennyway.common.annotation.UseCase; import kr.co.pennyway.domain.domains.question.domain.Question; import kr.co.pennyway.domain.domains.question.service.QuestionService; -import kr.co.pennyway.infra.client.google.mail.GoogleMailSender; +import kr.co.pennyway.infra.common.event.MailEvent; import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.ApplicationEventPublisher; @Slf4j @UseCase @AllArgsConstructor public class QuestionUseCase { private final QuestionService questionService; - private final GoogleMailSender googleMailSender; + private final ApplicationEventPublisher applicationEventPublisher; @Transactional public void sendQuestion(QuestionReq request) { Question question = request.toEntity(); questionService.createQuestion(question); - googleMailSender.sendMail(request.email(), request.content(), request.category().getTitle()); - // TODO : sendMail 메소드 이벤트 처리 + applicationEventPublisher.publishEvent(MailEvent.of(request.email(), request.content(), request.category().getTitle())); } } diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java index 797bcce32..f8634df04 100644 --- a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java @@ -27,7 +27,7 @@ public void sendMail(String email, String content, String category) { helper.setSubject(createSubject(email)); helper.setText(createContent(email, content, category), true); - javaMailSender.send(mimeMessage); + // javaMailSender.send(mimeMessage); } catch (Exception e) { log.warn(e.getMessage()); diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEvent.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEvent.java new file mode 100644 index 000000000..fcf6a0382 --- /dev/null +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEvent.java @@ -0,0 +1,11 @@ +package kr.co.pennyway.infra.common.event; + +public record MailEvent( + String email, + String content, + String category +) { + public static MailEvent of(String email, String content, String category) { + return new MailEvent(email, content, category); + } +} diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java new file mode 100644 index 000000000..cc4a6e720 --- /dev/null +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java @@ -0,0 +1,28 @@ +package kr.co.pennyway.infra.common.event; + +import kr.co.pennyway.infra.client.google.mail.GoogleMailSender; +import lombok.AllArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.event.EventListener; +import org.springframework.stereotype.Component; +import org.springframework.transaction.event.TransactionalEventListener; + +@Slf4j +@Component +@AllArgsConstructor +public class MailEventHandling { + GoogleMailSender googleMailSender; + + /** + * 관리자의 메일로 문의사항을 발송합니다. + *
+ * {@link EventListener}를 통해 createQuestion 트랜잭션 발생시 이벤트를 받아서 메일을 전송합니다. + * + * @param event {@link MailEvent} + */ + @TransactionalEventListener + public void handleMailEvent(MailEvent event) { + log.debug("handleMailEvent: {}", event); + googleMailSender.sendMail(event.email(), event.content(), event.category()); + } +} From ee6fa76399f223bd6633d0eec943f8db355d9b10 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Thu, 18 Apr 2024 00:19:45 +0900 Subject: [PATCH 35/42] =?UTF-8?q?test:=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/QuestionControllerTest.java | 123 ++++++++++++++++++ .../infra/common/event/MailEventHandling.java | 2 +- .../src/main/resources/application-infra.yml | 4 +- 3 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java diff --git a/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java b/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java new file mode 100644 index 000000000..53911a4e7 --- /dev/null +++ b/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java @@ -0,0 +1,123 @@ +package kr.co.pennyway.api.apis.question.controller; + +import com.fasterxml.jackson.databind.ObjectMapper; +import kr.co.pennyway.api.apis.question.dto.QuestionReq; +import kr.co.pennyway.api.config.ExternalApiIntegrationTest; +import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.ResultActions; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +//@WebMvcTest(controllers = QuestionController.class) +@ExternalApiIntegrationTest +@ActiveProfiles("local") +public class QuestionControllerTest { + + private final String expectedEmail = "test@gmail.com"; + private final String expectedContent = "test question content"; + private final QuestionCategory expectedCategory = QuestionCategory.ETC; + @Autowired + private MockMvc mockMvc; + @Autowired + private ObjectMapper objectMapper; + + @BeforeEach + void setUp(WebApplicationContext webApplicationContext) { + this.mockMvc = MockMvcBuilders + .webAppContextSetup(webApplicationContext) + .defaultRequest(post("/**"))//.with(csrf())) + .build(); + } + + @Test + @DisplayName("[1] 이메일, 내용을 필수로 입력해야 합니다.") + void requiredInputError() throws Exception { + // given + QuestionReq request = new QuestionReq("", "", QuestionCategory.ETC); + + // when + ResultActions resultActions = mockMvc.perform( + post("/v1/questions") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ); + + // then + resultActions + .andExpect(status().isUnprocessableEntity()) + .andExpect(jsonPath("$.fieldErrors.email").value("이메일을 입력해주세요")) + .andExpect(jsonPath("$.fieldErrors.content").value("문의 내용을 입력해주세요")) + .andDo(print()); + } + + @Test + @DisplayName("[2] 이메일 형식 오류입니다.") + void emailValidError() throws Exception { + // given + QuestionReq request = new QuestionReq("test", "test question content", QuestionCategory.ETC); + + // when + ResultActions resultActions = mockMvc.perform( + post("/v1/questions") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ); + + // then + resultActions + .andExpect(status().isUnprocessableEntity()) + .andExpect(jsonPath("$.fieldErrors.email").value("이메일 형식이 올바르지 않습니다.")) + .andDo(print()); + } + + @Test + @DisplayName(("[3] 문의 카테고리를 선택해주세요.")) + void categoryMissingError() throws Exception { + // given + QuestionReq request = new QuestionReq("team.collabu@gmail.com", "test question content", null); + + // when + ResultActions resultActions = mockMvc.perform( + post("/v1/questions") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ); + + // then + resultActions + .andExpect(status().isUnprocessableEntity()) + .andExpect(jsonPath("$.fieldErrors.category").value("문의 카테고리를 입력해주세요")) + .andDo(print()); + } + + @Test + @DisplayName("[4] 정상적인 문의 요청입니다.") + void sendQuestion() throws Exception { + // given + QuestionReq request = new QuestionReq(expectedEmail, expectedContent, expectedCategory); + + // when + ResultActions resultActions = mockMvc.perform( + post("/v1/questions") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request)) + ); + + // then + resultActions + .andExpect(status().isOk()) + .andDo(print()); + } +} diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java index cc4a6e720..754f69910 100644 --- a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java @@ -25,4 +25,4 @@ public void handleMailEvent(MailEvent event) { log.debug("handleMailEvent: {}", event); googleMailSender.sendMail(event.email(), event.content(), event.category()); } -} +} \ No newline at end of file diff --git a/pennyway-infra/src/main/resources/application-infra.yml b/pennyway-infra/src/main/resources/application-infra.yml index 3e4daaeb7..f459e2489 100644 --- a/pennyway-infra/src/main/resources/application-infra.yml +++ b/pennyway-infra/src/main/resources/application-infra.yml @@ -23,8 +23,8 @@ app: mail: host: smtp.gmail.com port: 587 - username: ${MAIL_USERNAME} - password: ${MAIL_PASSWORD} + username: ${MAIL_USERNAME:pennyway} + password: ${MAIL_PASSWORD:password} pennyway: server: From 4d53780adecb25e7069d46a525bd545fcdc77eef Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Thu, 18 Apr 2024 00:24:02 +0900 Subject: [PATCH 36/42] =?UTF-8?q?fix:=20mockbean=20=EB=88=84=EB=9D=BD=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 --- .../apis/question/controller/QuestionControllerTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java b/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java index 53911a4e7..257b305e4 100644 --- a/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java +++ b/pennyway-app-external-api/src/test/java/kr/co/pennyway/api/apis/question/controller/QuestionControllerTest.java @@ -2,12 +2,14 @@ import com.fasterxml.jackson.databind.ObjectMapper; import kr.co.pennyway.api.apis.question.dto.QuestionReq; -import kr.co.pennyway.api.config.ExternalApiIntegrationTest; +import kr.co.pennyway.api.apis.question.usecase.QuestionUseCase; import kr.co.pennyway.domain.domains.question.domain.QuestionCategory; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.web.servlet.MockMvc; @@ -20,8 +22,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; -//@WebMvcTest(controllers = QuestionController.class) -@ExternalApiIntegrationTest +@WebMvcTest(controllers = QuestionController.class) @ActiveProfiles("local") public class QuestionControllerTest { @@ -32,6 +33,8 @@ public class QuestionControllerTest { private MockMvc mockMvc; @Autowired private ObjectMapper objectMapper; + @MockBean + private QuestionUseCase questionUseCase; @BeforeEach void setUp(WebApplicationContext webApplicationContext) { From d444b1e5ff80ce35823d9db82d3e9757edccbecc Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Thu, 18 Apr 2024 00:38:01 +0900 Subject: [PATCH 37/42] =?UTF-8?q?fix:=20=ED=85=8C=EC=8A=A4=ED=8C=85?= =?UTF-8?q?=EA=B0=84=20=EB=A1=9C=EC=A7=81=20=EC=9E=84=EC=8B=9C=20=EC=A3=BC?= =?UTF-8?q?=EC=84=9D=EC=B2=98=EB=A6=AC=20=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../co/pennyway/infra/client/google/mail/GoogleMailSender.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java index f8634df04..797bcce32 100644 --- a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java @@ -27,7 +27,7 @@ public void sendMail(String email, String content, String category) { helper.setSubject(createSubject(email)); helper.setText(createContent(email, content, category), true); - // javaMailSender.send(mimeMessage); + javaMailSender.send(mimeMessage); } catch (Exception e) { log.warn(e.getMessage()); From 9eae3eea523b76149eae0c77b0259d481e6c24a7 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Fri, 19 Apr 2024 23:30:14 +0900 Subject: [PATCH 38/42] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20getter=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../domains/question/domain/QuestionCategory.java | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java index f47a242cd..6fabf68b1 100644 --- a/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java +++ b/pennyway-domain/src/main/java/kr/co/pennyway/domain/domains/question/domain/QuestionCategory.java @@ -9,16 +9,11 @@ @RequiredArgsConstructor(access = AccessLevel.PRIVATE) @Getter public enum QuestionCategory implements LegacyCommonType { - UTILIZATION("1","이용 관련"), - BUG_REPORT("2","오류 신고"), - SUGGESTION("3","서비스 제안"), - ETC("4","기타"); + UTILIZATION("1", "이용 관련"), + BUG_REPORT("2", "오류 신고"), + SUGGESTION("3", "서비스 제안"), + ETC("4", "기타"); private final String code; private final String title; - - @Override - public String getCode(){ - return code; - } } From 67f7c9eedf7bad98a9656c00dc209a4f5dd1deee Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Fri, 19 Apr 2024 23:31:09 +0900 Subject: [PATCH 39/42] =?UTF-8?q?fix:=20main=ED=95=B8=EB=93=A4=EB=A7=81=20?= =?UTF-8?q?log=20=EC=88=98=EC=A4=80=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kr/co/pennyway/infra/common/event/MailEventHandling.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java index 754f69910..3ada82e56 100644 --- a/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/common/event/MailEventHandling.java @@ -22,7 +22,7 @@ public class MailEventHandling { */ @TransactionalEventListener public void handleMailEvent(MailEvent event) { - log.debug("handleMailEvent: {}", event); + log.info("handleMailEvent: {}", event); googleMailSender.sendMail(event.email(), event.content(), event.category()); } } \ No newline at end of file From 2ae3a8fafb54a32ba1948e410b5c1814798ada9e Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Fri, 19 Apr 2024 23:35:57 +0900 Subject: [PATCH 40/42] =?UTF-8?q?feat:=20admin=5Faddress=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EB=B3=80=EC=88=98=20=EA=B8=B0=EB=B3=B8=EA=B0=92=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 --- pennyway-infra/src/main/resources/application-infra.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennyway-infra/src/main/resources/application-infra.yml b/pennyway-infra/src/main/resources/application-infra.yml index f459e2489..cf0b4cc83 100644 --- a/pennyway-infra/src/main/resources/application-infra.yml +++ b/pennyway-infra/src/main/resources/application-infra.yml @@ -19,7 +19,7 @@ spring: static: ${AWS_SNS_REGION:republic-of-korea-1} app: - question-address: ${ADMIN_ADDRESS} + question-address: ${ADMIN_ADDRESS:team.collabu@gmail.com} mail: host: smtp.gmail.com port: 587 From b28333c89a6a712c0f94292ab382f1ecfb017d24 Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Sat, 20 Apr 2024 17:50:47 +0900 Subject: [PATCH 41/42] =?UTF-8?q?fix:=20=EB=A9=94=EC=9D=BC=20=EB=B0=9C?= =?UTF-8?q?=EC=86=A1=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20=EC=8B=A4=ED=8C=A8?= =?UTF-8?q?=EC=8B=9C=20=EB=A1=9C=EA=B7=B8=20=EB=A0=88=EB=B2=A8=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 --- .../pennyway/infra/client/google/mail/GoogleMailSender.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java index 797bcce32..db12c5bfd 100644 --- a/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java +++ b/pennyway-infra/src/main/java/kr/co/pennyway/infra/client/google/mail/GoogleMailSender.java @@ -29,9 +29,9 @@ public void sendMail(String email, String content, String category) { javaMailSender.send(mimeMessage); } catch (Exception e) { - log.warn(e.getMessage()); + log.error("MailSender exception:" + e.getMessage()); - throw new IllegalArgumentException(e.getMessage()); + throw new RuntimeException("메일 전송에 실패했습니다."); } } From bb2358d2b99a925d139b36be2385119eb16bae1b Mon Sep 17 00:00:00 2001 From: DinoDeveloper Date: Sat, 20 Apr 2024 18:00:08 +0900 Subject: [PATCH 42/42] =?UTF-8?q?feat:=20swagger=20=EC=84=B1=EA=B3=B5=20?= =?UTF-8?q?=EC=9D=91=EB=8B=B5=20=EB=AA=85=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pennyway/api/apis/question/api/QuestionApi.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java index e2ffb5518..ca0cbb714 100644 --- a/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java +++ b/pennyway-app-external-api/src/main/java/kr/co/pennyway/api/apis/question/api/QuestionApi.java @@ -1,6 +1,9 @@ package kr.co.pennyway.api.apis.question.api; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.ExampleObject; +import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.tags.Tag; import kr.co.pennyway.api.apis.question.dto.QuestionReq; import org.springframework.http.ResponseEntity; @@ -11,5 +14,13 @@ public interface QuestionApi { @Operation(summary = "문의 전송", description = "사용자는 관리자에게 문의 메일을 발송한다.") + @ApiResponse(responseCode = "200", content = @Content(mediaType = "application/json", examples = { + @ExampleObject(name = "발신 성공", value = """ + { + "code": "2000", + "data": {} + } + """) + })) ResponseEntity sendQuestion(@RequestBody @Validated QuestionReq request); }