From 908586134e5ebe9f6fe5bd6ec6912aad4c96bbae Mon Sep 17 00:00:00 2001 From: parksey Date: Sun, 3 Sep 2023 03:20:22 +0900 Subject: [PATCH 1/7] =?UTF-8?q?[JT-28]=20feat:=20SMTP=EB=A5=BC=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20=EC=9D=B4=EB=A9=94=EC=9D=BC=20=EC=9D=B8?= =?UTF-8?q?=EC=A6=9D=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- module-domain/build.gradle | 3 ++ .../jtoon/global/config/MailConfig.java | 37 +++++++++++++++++++ .../jtoon/smtp/application/SmtpService.java | 36 ++++++++++++++++++ .../smtp/application/SmtpServiceTest.java | 17 +++++++++ .../jtoon/exception/ExceptionCode.java | 1 + 5 files changed, 94 insertions(+) create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java create mode 100644 module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java diff --git a/module-domain/build.gradle b/module-domain/build.gradle index 2ed55fee..d0d28ec9 100644 --- a/module-domain/build.gradle +++ b/module-domain/build.gradle @@ -11,4 +11,7 @@ dependencies { // Bean Validation implementation 'org.springframework.boot:spring-boot-starter-validation' + + // SMTP + implementation 'org.springframework.boot:spring-boot-starter-mail' } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java b/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java new file mode 100644 index 00000000..219a0c32 --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java @@ -0,0 +1,37 @@ +package com.devtoon.jtoon.global.config; + +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 { + + @Bean + public JavaMailSender javaMailSender() { + JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); + + javaMailSender.setHost("smtp.google.com"); + javaMailSender.setUsername("saeyun302@gmail.com"); + javaMailSender.setPassword("konhyzsxozaoejnc"); + javaMailSender.setPort(587); + + javaMailSender.setJavaMailProperties(getMailProperties()); + + return javaMailSender; + } + + private Properties getMailProperties() { + Properties properties = new Properties(); + properties.setProperty("mail.transport.protocol", "smtp"); + properties.setProperty("mail.smtp.auth", "true"); + properties.setProperty("mail.smtp.starttls.enable", "true"); + properties.setProperty("mail.debug", "true"); +// properties.setProperty("mail.smtp.ssl.trust","smtp.google.com"); +// properties.setProperty("mail.smtp.starttls.enable","true"); + return properties; + } +} diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java new file mode 100644 index 00000000..16f9480e --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java @@ -0,0 +1,36 @@ +package com.devtoon.jtoon.smtp.application; + +import com.devtoon.jtoon.exception.ExceptionCode; +import com.devtoon.jtoon.exception.MemberException; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.mail.MailException; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + +@Slf4j +@Service +@RequiredArgsConstructor +public class SmtpService { + + private final JavaMailSender javaMailSender; + + public void sendMail(String to, String randomNumber) { + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + + try { + MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8"); + mimeMessageHelper.setTo(to); + mimeMessageHelper.setSubject("JTOON 이메일 인증"); + mimeMessageHelper.setText(randomNumber); + javaMailSender.send(mimeMessage); + + } catch (MessagingException | MailException e) { + log.error("이메일 생성 실패", e); + throw new MemberException(ExceptionCode.MEMBER_MESSAGE_SEND_FAILED); + } + } +} diff --git a/module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java b/module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java new file mode 100644 index 00000000..9de178ad --- /dev/null +++ b/module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java @@ -0,0 +1,17 @@ +package com.devtoon.jtoon.smtp.application; + +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; + +@SpringBootTest +class SmtpServiceTest { + + @Autowired + SmtpService smtpService; + + @Test + void test_Email() { + smtpService.sendMail("parkseyeon99@naver.com", "123456"); + } +} \ No newline at end of file diff --git a/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java b/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java index 640ca93b..44f78ff4 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java @@ -14,6 +14,7 @@ public enum ExceptionCode { MEMBER_PHONE_INVALID_FORMAT("올바른 전화번호 형식이 아닙니다."), MEMBER_ROLE_INVALID_FORMAT("올바른 회원 역할이 아닙니다"), MEMBER_LOGIN_TYPE_INVALID_FORMAT("올바른 로그인 타입이 아닙니다."), + MEMBER_MESSAGE_SEND_FAILED("이메일 인증 메세지 전송 실패") ; private final String message; From 137322d4b60c2016d10bc68b21f8dfbe29dc2591 Mon Sep 17 00:00:00 2001 From: ymkim97 Date: Sun, 3 Sep 2023 16:09:42 +0900 Subject: [PATCH 2/7] =?UTF-8?q?[JT-28]=20feat:=20=EC=9D=B4=EB=A9=94?= =?UTF-8?q?=EC=9D=BC=20=EC=9D=B8=EC=A6=9D=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 17 +++++++--- .../jtoon/smtp/application/SmtpService.java | 19 ++++++------ .../com/devtoon/jtoon/smtp/entity/Mail.java | 31 +++++++++++++++++++ 3 files changed, 54 insertions(+), 13 deletions(-) create mode 100644 module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java diff --git a/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java b/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java index 849ecf4e..94def742 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java @@ -1,16 +1,19 @@ package com.devtoon.jtoon.member.presentation; -import com.devtoon.jtoon.member.application.MemberService; -import com.devtoon.jtoon.member.request.SignUpDto; -import jakarta.validation.Valid; -import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import com.devtoon.jtoon.member.application.MemberService; +import com.devtoon.jtoon.member.request.SignUpDto; +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + @RestController @RequiredArgsConstructor @RequestMapping("/members") @@ -25,4 +28,10 @@ public ResponseEntity signUp(@RequestBody @Valid SignUpDto signUpDto) { return new ResponseEntity<>(HttpStatus.CREATED); } + @GetMapping("/email-authorize") + public ResponseEntity emailAuthentication(@RequestParam(value = "email", required = true) String email) { + String authenticationUuid = memberService.sendEmailAuthentication(email); + + return ResponseEntity.status(HttpStatus.OK).body(authenticationUuid); + } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java index 16f9480e..386c8b10 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java @@ -1,15 +1,17 @@ package com.devtoon.jtoon.smtp.application; +import org.springframework.mail.MailException; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Service; + import com.devtoon.jtoon.exception.ExceptionCode; import com.devtoon.jtoon.exception.MemberException; +import com.devtoon.jtoon.smtp.entity.Mail; import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.springframework.mail.MailException; -import org.springframework.mail.javamail.JavaMailSender; -import org.springframework.mail.javamail.MimeMessageHelper; -import org.springframework.stereotype.Service; @Slf4j @Service @@ -18,18 +20,17 @@ public class SmtpService { private final JavaMailSender javaMailSender; - public void sendMail(String to, String randomNumber) { + public void sendMail(Mail mail) { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); try { MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true, "utf-8"); - mimeMessageHelper.setTo(to); - mimeMessageHelper.setSubject("JTOON 이메일 인증"); - mimeMessageHelper.setText(randomNumber); + mimeMessageHelper.setTo(mail.getTo()); + mimeMessageHelper.setSubject(mail.getSubject()); + mimeMessageHelper.setText(mail.getText()); javaMailSender.send(mimeMessage); } catch (MessagingException | MailException e) { - log.error("이메일 생성 실패", e); throw new MemberException(ExceptionCode.MEMBER_MESSAGE_SEND_FAILED); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java b/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java new file mode 100644 index 00000000..38a22a41 --- /dev/null +++ b/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java @@ -0,0 +1,31 @@ +package com.devtoon.jtoon.smtp.entity; + +import lombok.Getter; + +@Getter +public class Mail { + + private static final String DEFAULT_SUBJECT = "[JTOON] 이메일 관련 인증입니다."; + + private String subject = DEFAULT_SUBJECT; + private String to; + private String text; + + private Mail(String to, String text) { + this.to = to; + this.text = text; + } + + private Mail(String subject, String to, String text) { + this(to, text); + this.subject = subject; + } + + public static Mail createEvent(String subject, String to, String text) { + return new Mail(subject, to, text); + } + + public static Mail createAuthentication(String to, String text) { + return new Mail(to, text); + } +} From eab98c642af25f3055046bd4e3ac4e85b3de6298 Mon Sep 17 00:00:00 2001 From: ymkim97 Date: Sun, 3 Sep 2023 16:11:40 +0900 Subject: [PATCH 3/7] =?UTF-8?q?[JT-28]=20feat:=20=EB=B9=84=EB=B0=80?= =?UTF-8?q?=EB=B2=88=ED=98=B8=20=EC=95=94=ED=98=B8=ED=99=94=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 1 + module-domain/build.gradle | 4 +++ .../member/application/MemberService.java | 34 ++++++++++++++++++- .../member/repository/MemberRepository.java | 1 + .../jtoon/member/request/SignUpDto.java | 4 +-- module-internal/build.gradle | 3 ++ .../config/WebSecurityConfiguration.java | 17 ++++++++++ 7 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java diff --git a/build.gradle b/build.gradle index 1db7198c..324b2461 100644 --- a/build.gradle +++ b/build.gradle @@ -51,6 +51,7 @@ project(':module-domain') { dependencies { implementation project(':module-core') + implementation project(':module-internal') } } diff --git a/module-domain/build.gradle b/module-domain/build.gradle index d0d28ec9..f9c73b58 100644 --- a/module-domain/build.gradle +++ b/module-domain/build.gradle @@ -14,4 +14,8 @@ dependencies { // SMTP implementation 'org.springframework.boot:spring-boot-starter-mail' + testImplementation 'com.icegreen:greenmail:2.1.0-alpha-2' + + // Security + implementation 'org.springframework.boot:spring-boot-starter-security' } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java b/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java index f7071db5..55f69382 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java @@ -1,20 +1,52 @@ package com.devtoon.jtoon.member.application; +import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import com.devtoon.jtoon.exception.ExceptionCode; +import com.devtoon.jtoon.exception.MemberException; import com.devtoon.jtoon.member.entity.Member; import com.devtoon.jtoon.member.repository.MemberRepository; import com.devtoon.jtoon.member.request.SignUpDto; +import com.devtoon.jtoon.smtp.application.SmtpService; +import com.devtoon.jtoon.smtp.entity.Mail; +import java.util.UUID; import lombok.RequiredArgsConstructor; @Service +@Transactional(readOnly = true) @RequiredArgsConstructor public class MemberService { + private final SmtpService smtpService; private final MemberRepository memberRepository; + private final PasswordEncoder passwordEncoder; + @Transactional public void createMember(SignUpDto signUpDto) { - Member member = signUpDto.toEntity(); + isEmailExist(signUpDto.email()); + + String encryptedPassword = passwordEncoder.encode(signUpDto.password()); + Member member = signUpDto.toEntity(encryptedPassword); + memberRepository.save(member); } + + public String sendEmailAuthentication(String email) { + isEmailExist(email); + + UUID uuid = UUID.randomUUID(); + String randomUuid = uuid.toString().substring(0,6); + Mail mail = Mail.createAuthentication(email, randomUuid); + smtpService.sendMail(mail); + + return randomUuid; + } + + private void isEmailExist(String email) { + if (memberRepository.existsByEmail(email)) { + throw new MemberException(ExceptionCode.MEMBER_EMAIL_CONFLICT); + } + } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java b/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java index 1c72e5c0..b26b5125 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java @@ -5,4 +5,5 @@ import com.devtoon.jtoon.member.entity.Member; public interface MemberRepository extends JpaRepository { + boolean existsByEmail(String email); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java b/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java index c9c886dc..fe32c03f 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java @@ -21,10 +21,10 @@ public record SignUpDto( @NotNull String loginType ) { - public Member toEntity() { + public Member toEntity(String encryptedPassword) { return Member.builder() .email(email) - .password(password) + .password(encryptedPassword) .name(name) .nickname(nickname) .gender(Gender.generate(gender)) diff --git a/module-internal/build.gradle b/module-internal/build.gradle index e0c58467..fd78076c 100644 --- a/module-internal/build.gradle +++ b/module-internal/build.gradle @@ -1,4 +1,7 @@ dependencies { // Web implementation 'org.springframework.boot:spring-boot-starter-web' + + // Security + implementation 'org.springframework.boot:spring-boot-starter-security' } diff --git a/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java b/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java new file mode 100644 index 00000000..c28e57dd --- /dev/null +++ b/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java @@ -0,0 +1,17 @@ +package com.devtoon.jtoon.security.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@Configuration +@EnableWebSecurity +public class WebSecurityConfiguration { + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(); + } +} From 38bea836b9bfce3ae8f79babf2fa43cd17099284 Mon Sep 17 00:00:00 2001 From: ymkim97 Date: Sun, 3 Sep 2023 16:14:24 +0900 Subject: [PATCH 4/7] =?UTF-8?q?[JT-28]=20refactor:=20Member=20entity=20val?= =?UTF-8?q?idation=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Enum unmodifiable Map 수정 - Enum private 생성자 추가 --- .../devtoon/jtoon/member/entity/Gender.java | 12 ++-- .../jtoon/member/entity/LoginType.java | 13 ++-- .../devtoon/jtoon/member/entity/Member.java | 67 +++++++++---------- .../com/devtoon/jtoon/member/entity/Role.java | 4 ++ .../devtoon/jtoon/member/entity/Status.java | 4 ++ .../jtoon/exception/ExceptionCode.java | 8 +-- .../jtoon/exception/MemberException.java | 6 +- 7 files changed, 65 insertions(+), 49 deletions(-) diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java index aaab65b4..e9e7f400 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java @@ -3,19 +3,23 @@ import com.devtoon.jtoon.exception.ExceptionCode; import com.devtoon.jtoon.exception.MemberException; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +@AllArgsConstructor(access = AccessLevel.PRIVATE) public enum Gender { MALE, FEMALE; private static final Map GENDER_MAP; static { - GENDER_MAP = new HashMap<>(); - Arrays.stream(Gender.values()) - .forEach(gender -> GENDER_MAP.put(gender.name(), gender)); + GENDER_MAP = Collections.unmodifiableMap( + Arrays.stream(Gender.values()) + .collect(Collectors.toMap(Enum::name, gender -> gender))); } public static Gender generate(String gender) { diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java index 1aa14876..303eac1d 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java @@ -3,10 +3,14 @@ import com.devtoon.jtoon.exception.ExceptionCode; import com.devtoon.jtoon.exception.MemberException; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +@AllArgsConstructor(access = AccessLevel.PRIVATE) public enum LoginType { LOCAL, NAVER, @@ -15,9 +19,10 @@ public enum LoginType { private static final Map LOGIN_TYPE_MAP; static { - LOGIN_TYPE_MAP = new HashMap<>(); - Arrays.stream(LoginType.values()) - .forEach(loginType -> LOGIN_TYPE_MAP.put(loginType.name(), loginType)); + LOGIN_TYPE_MAP = Collections.unmodifiableMap( + Arrays.stream(LoginType.values()) + .collect(Collectors.toMap(LoginType::name, loginType -> loginType)) + ); } public static LoginType generate(String loginType) { diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java index 9ffe7f04..4a8ab404 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java @@ -1,8 +1,8 @@ package com.devtoon.jtoon.member.entity; -import com.devtoon.jtoon.global.common.BaseTimeEntity; import com.devtoon.jtoon.exception.ExceptionCode; import com.devtoon.jtoon.exception.MemberException; +import com.devtoon.jtoon.global.common.BaseTimeEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.EnumType; @@ -12,6 +12,7 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import java.time.LocalDateTime; +import java.util.Objects; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -65,49 +66,43 @@ public class Member extends BaseTimeEntity { @Builder private Member(String email, String password, String name, String nickname, Gender gender, String phone, Role role, LoginType loginType) { - this.email = validateEmailNotNullAndGet(email); - this.password = validatePasswordNotNullAndGet(password); - this.name = validateNameNotNullAndGet(name); - this.nickname = validateNicknameNotNullAndGet(nickname); - this.gender = validateGenderNotNullAndGet(gender); - this.phone = validatePhoneNotNullAndGet(phone); + this.email = Objects.requireNonNull(email, ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT.getMessage()); + this.password = Objects.requireNonNull(password, ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT.getMessage()); + this.name = Objects.requireNonNull(name, ExceptionCode.MEMBER_NAME_INVALID_FORMAT.getMessage()); + this.nickname = Objects.requireNonNull(nickname, ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT.getMessage()); + this.gender = Objects.requireNonNull(gender, ExceptionCode.MEMBER_GENDER_INVALID_FORMAT.getMessage()); + this.phone = Objects.requireNonNull(phone, ExceptionCode.MEMBER_PHONE_INVALID_FORMAT.getMessage()); this.role = role; this.loginType = loginType; } - private String validateEmailNotNullAndGet(String data) { - validateNotNull(data, ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT); - return data; - } - - private String validatePasswordNotNullAndGet(String data) { - validateNotNull(data, ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT); - return data; - } - - private String validateNameNotNullAndGet(String data) { - validateNotNull(data, ExceptionCode.MEMBER_NAME_INVALID_FORMAT); - return data; + private void valid() { + this.email = Objects.requireNonNullElseGet(email, () -> { + throw new MemberException(ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT); + }); + this.password = Objects.requireNonNull(password, () -> { + throw new MemberException(ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT); + }); + this.name = Objects.requireNonNull(name, () -> { + throw new MemberException(ExceptionCode.MEMBER_NAME_INVALID_FORMAT); + }); + this.nickname = Objects.requireNonNull(nickname, () -> { + throw new MemberException(ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT); + }); } - private String validateNicknameNotNullAndGet(String data) { - validateNotNull(data, ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT); - return data; - } - private Gender validateGenderNotNullAndGet(Gender gender) { - validateNotNull(gender, ExceptionCode.MEMBER_GENDER_INVALID_FORMAT); - return gender; - } - - private String validatePhoneNotNullAndGet(String data) { - validateNotNull(data, ExceptionCode.MEMBER_PHONE_INVALID_FORMAT); - return data; - } - private void validateNotNull(T data, ExceptionCode exceptionCode) { - if (data == null) { - throw new MemberException(exceptionCode); + private void valid2() { + try { + Objects.requireNonNull(email, ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT.getMessage()); + Objects.requireNonNull(password, ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT.getMessage()); + Objects.requireNonNull(name, ExceptionCode.MEMBER_NAME_INVALID_FORMAT.getMessage()); + Objects.requireNonNull(nickname, ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT.getMessage()); + Objects.requireNonNull(gender, ExceptionCode.MEMBER_GENDER_INVALID_FORMAT.getMessage()); + Objects.requireNonNull(phone, ExceptionCode.MEMBER_PHONE_INVALID_FORMAT.getMessage()); + } catch (NullPointerException exception) { + throw new MemberException(exception.getMessage()); } } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java index 2c76db0d..e9828b96 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java @@ -1,5 +1,9 @@ package com.devtoon.jtoon.member.entity; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) public enum Role { USER, ADMIN } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Status.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Status.java index 62145759..15a1cc6f 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Status.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Status.java @@ -1,5 +1,9 @@ package com.devtoon.jtoon.member.entity; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) public enum Status { NORMAL, REST, diff --git a/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java b/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java index 44f78ff4..b674b962 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/exception/ExceptionCode.java @@ -1,8 +1,10 @@ package com.devtoon.jtoon.exception; import lombok.AccessLevel; +import lombok.Getter; import lombok.RequiredArgsConstructor; +@Getter @RequiredArgsConstructor(access = AccessLevel.PRIVATE) public enum ExceptionCode { @@ -14,12 +16,10 @@ public enum ExceptionCode { MEMBER_PHONE_INVALID_FORMAT("올바른 전화번호 형식이 아닙니다."), MEMBER_ROLE_INVALID_FORMAT("올바른 회원 역할이 아닙니다"), MEMBER_LOGIN_TYPE_INVALID_FORMAT("올바른 로그인 타입이 아닙니다."), - MEMBER_MESSAGE_SEND_FAILED("이메일 인증 메세지 전송 실패") + MEMBER_MESSAGE_SEND_FAILED("이메일 인증 메세지 전송 실패"), + MEMBER_EMAIL_CONFLICT("Email 중복") ; private final String message; - public String getMessage() { - return message; - } } diff --git a/module-internal/src/main/java/com/devtoon/jtoon/exception/MemberException.java b/module-internal/src/main/java/com/devtoon/jtoon/exception/MemberException.java index 14451a7f..95922c1e 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/exception/MemberException.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/exception/MemberException.java @@ -2,7 +2,11 @@ public class MemberException extends RuntimeException { - private final ExceptionCode exceptionCode; + private ExceptionCode exceptionCode; + + public MemberException(String message) { + super(message); + } public MemberException(ExceptionCode exceptionCode) { this.exceptionCode = exceptionCode; From 3efc8fb4ca33113c4566928d4618cad2b4b57465 Mon Sep 17 00:00:00 2001 From: ymkim97 Date: Mon, 4 Sep 2023 11:38:17 +0900 Subject: [PATCH 5/7] =?UTF-8?q?[JT-28]=20feat:=20=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EA=B0=80=EC=9E=85=20=EA=B8=B0=EB=8A=A5=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 2 +- .../src/main/resources/application.yml | 2 +- module-domain/build.gradle | 1 - .../jtoon/global/config/MailConfig.java | 24 +++-- .../util/{MemberRegExp.java => RegExp.java} | 2 +- .../member/application/MemberService.java | 2 +- .../devtoon/jtoon/member/entity/Member.java | 31 ------- .../jtoon/member/request/SignUpDto.java | 2 +- .../jtoon/smtp/application/SmtpService.java | 2 - .../application/MemberServiceTest.java | 2 +- .../repository/MemberRepositoryTest.java | 91 ------------------- .../jtoon/member/request/SignUpDtoTest.java | 24 ----- .../jtoon/member/util/MemberRegExpTest.java | 47 ---------- .../smtp/application/SmtpServiceTest.java | 17 ---- 14 files changed, 24 insertions(+), 225 deletions(-) rename module-domain/src/main/java/com/devtoon/jtoon/global/util/{MemberRegExp.java => RegExp.java} (96%) rename module-domain/src/test/java/com/devtoon/jtoon/{ => member}/application/MemberServiceTest.java (85%) delete mode 100644 module-domain/src/test/java/com/devtoon/jtoon/member/repository/MemberRepositoryTest.java delete mode 100644 module-domain/src/test/java/com/devtoon/jtoon/member/request/SignUpDtoTest.java delete mode 100644 module-domain/src/test/java/com/devtoon/jtoon/member/util/MemberRegExpTest.java delete mode 100644 module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java diff --git a/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java b/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java index 94def742..dfbcf641 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java @@ -29,7 +29,7 @@ public ResponseEntity signUp(@RequestBody @Valid SignUpDto signUpDto) { } @GetMapping("/email-authorize") - public ResponseEntity emailAuthentication(@RequestParam(value = "email", required = true) String email) { + public ResponseEntity authenticateEmail(@RequestParam(value = "email", required = true) String email) { String authenticationUuid = memberService.sendEmailAuthentication(email); return ResponseEntity.status(HttpStatus.OK).body(authenticationUuid); diff --git a/module-application/src/main/resources/application.yml b/module-application/src/main/resources/application.yml index ee283d7a..92374faf 100644 --- a/module-application/src/main/resources/application.yml +++ b/module-application/src/main/resources/application.yml @@ -1,3 +1,3 @@ spring: profiles: - include: s3 + include: s3, smtp diff --git a/module-domain/build.gradle b/module-domain/build.gradle index f9c73b58..767c74d5 100644 --- a/module-domain/build.gradle +++ b/module-domain/build.gradle @@ -1,7 +1,6 @@ dependencies { // JPA implementation 'org.springframework.boot:spring-boot-starter-data-jpa' - implementation project(path: ':module-internal') // Test testImplementation 'org.springframework.boot:spring-boot-starter-test' diff --git a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java b/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java index 219a0c32..01d26d97 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java @@ -1,5 +1,6 @@ package com.devtoon.jtoon.global.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; @@ -9,15 +10,27 @@ @Configuration public class MailConfig { + + @Value("${smtp.username}") + private String username; + + @Value("${smtp.password}") + private String password; + + @Value("${smtp.host}") + private String host; + + @Value("${smtp.port}") + private Integer port; @Bean public JavaMailSender javaMailSender() { JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); - javaMailSender.setHost("smtp.google.com"); - javaMailSender.setUsername("saeyun302@gmail.com"); - javaMailSender.setPassword("konhyzsxozaoejnc"); - javaMailSender.setPort(587); + javaMailSender.setHost(host); + javaMailSender.setUsername(username); + javaMailSender.setPassword(password); + javaMailSender.setPort(port); javaMailSender.setJavaMailProperties(getMailProperties()); @@ -30,8 +43,7 @@ private Properties getMailProperties() { properties.setProperty("mail.smtp.auth", "true"); properties.setProperty("mail.smtp.starttls.enable", "true"); properties.setProperty("mail.debug", "true"); -// properties.setProperty("mail.smtp.ssl.trust","smtp.google.com"); -// properties.setProperty("mail.smtp.starttls.enable","true"); + properties.setProperty("mail.smtp.ssl.trust","smtp.google.com"); return properties; } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/global/util/MemberRegExp.java b/module-domain/src/main/java/com/devtoon/jtoon/global/util/RegExp.java similarity index 96% rename from module-domain/src/main/java/com/devtoon/jtoon/global/util/MemberRegExp.java rename to module-domain/src/main/java/com/devtoon/jtoon/global/util/RegExp.java index c3629682..ff69d22d 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/global/util/MemberRegExp.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/global/util/RegExp.java @@ -10,7 +10,7 @@ */ @NoArgsConstructor(access = AccessLevel.PRIVATE) -public class MemberRegExp { +public class RegExp { public static final String EMAIL_PATTERN = "[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?"; public static final String PHONE_PATTERN = "^01([0|1|6|7|8|9])+?([0-9]{4})+?([0-9]{4})$"; diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java b/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java index 55f69382..496dfeea 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java @@ -37,7 +37,7 @@ public String sendEmailAuthentication(String email) { isEmailExist(email); UUID uuid = UUID.randomUUID(); - String randomUuid = uuid.toString().substring(0,6); + String randomUuid = uuid.toString().substring(0, 6); Mail mail = Mail.createAuthentication(email, randomUuid); smtpService.sendMail(mail); diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java index 4a8ab404..cd61df8d 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java @@ -1,7 +1,6 @@ package com.devtoon.jtoon.member.entity; import com.devtoon.jtoon.exception.ExceptionCode; -import com.devtoon.jtoon.exception.MemberException; import com.devtoon.jtoon.global.common.BaseTimeEntity; import jakarta.persistence.Column; import jakarta.persistence.Entity; @@ -75,34 +74,4 @@ private Member(String email, String password, String name, String nickname, Gend this.role = role; this.loginType = loginType; } - - private void valid() { - this.email = Objects.requireNonNullElseGet(email, () -> { - throw new MemberException(ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT); - }); - this.password = Objects.requireNonNull(password, () -> { - throw new MemberException(ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT); - }); - this.name = Objects.requireNonNull(name, () -> { - throw new MemberException(ExceptionCode.MEMBER_NAME_INVALID_FORMAT); - }); - this.nickname = Objects.requireNonNull(nickname, () -> { - throw new MemberException(ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT); - }); - } - - - - private void valid2() { - try { - Objects.requireNonNull(email, ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT.getMessage()); - Objects.requireNonNull(password, ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT.getMessage()); - Objects.requireNonNull(name, ExceptionCode.MEMBER_NAME_INVALID_FORMAT.getMessage()); - Objects.requireNonNull(nickname, ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT.getMessage()); - Objects.requireNonNull(gender, ExceptionCode.MEMBER_GENDER_INVALID_FORMAT.getMessage()); - Objects.requireNonNull(phone, ExceptionCode.MEMBER_PHONE_INVALID_FORMAT.getMessage()); - } catch (NullPointerException exception) { - throw new MemberException(exception.getMessage()); - } - } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java b/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java index fe32c03f..cf01446f 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java @@ -1,6 +1,6 @@ package com.devtoon.jtoon.member.request; -import static com.devtoon.jtoon.global.util.MemberRegExp.*; +import static com.devtoon.jtoon.global.util.RegExp.*; import com.devtoon.jtoon.member.entity.Gender; import com.devtoon.jtoon.member.entity.LoginType; diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java index 386c8b10..633fa91f 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java @@ -11,9 +11,7 @@ import jakarta.mail.MessagingException; import jakarta.mail.internet.MimeMessage; import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -@Slf4j @Service @RequiredArgsConstructor public class SmtpService { diff --git a/module-domain/src/test/java/com/devtoon/jtoon/application/MemberServiceTest.java b/module-domain/src/test/java/com/devtoon/jtoon/member/application/MemberServiceTest.java similarity index 85% rename from module-domain/src/test/java/com/devtoon/jtoon/application/MemberServiceTest.java rename to module-domain/src/test/java/com/devtoon/jtoon/member/application/MemberServiceTest.java index d22a9a6b..4dd9d167 100644 --- a/module-domain/src/test/java/com/devtoon/jtoon/application/MemberServiceTest.java +++ b/module-domain/src/test/java/com/devtoon/jtoon/member/application/MemberServiceTest.java @@ -1,4 +1,4 @@ -package com.devtoon.jtoon.application; +package com.devtoon.jtoon.member.application; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Nested; diff --git a/module-domain/src/test/java/com/devtoon/jtoon/member/repository/MemberRepositoryTest.java b/module-domain/src/test/java/com/devtoon/jtoon/member/repository/MemberRepositoryTest.java deleted file mode 100644 index d6c31e44..00000000 --- a/module-domain/src/test/java/com/devtoon/jtoon/member/repository/MemberRepositoryTest.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.devtoon.jtoon.member.repository; - -import static org.assertj.core.api.Assertions.*; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; - -import com.devtoon.jtoon.annotation.JpaHelper; -import com.devtoon.jtoon.exception.MemberException; -import com.devtoon.jtoon.member.entity.Gender; -import com.devtoon.jtoon.member.entity.LoginType; -import com.devtoon.jtoon.member.entity.Member; -import com.devtoon.jtoon.member.entity.Role; - -@DisplayName("회원 Repository 테스트") -class MemberRepositoryTest extends JpaHelper { - - @Autowired - MemberRepository memberRepository; - - @Nested - @DisplayName("회원 도메인 테스트") - class MemberCreateTest { - - @Test - @DisplayName("회원 생성 성공 테스트") - void create_member_success_test() { - // given - Member member = Member.builder() - .email("abc123@naver.com") - .password("qwer1234") - .phone("01012345678") - .gender(Gender.MALE) - .nickname("nikuname") - .name("parksey") - .loginType(LoginType.LOCAL) - .role(Role.USER) - .build(); - - // when - Member savedMember = memberRepository.save(member); - - // then - assertThat(savedMember.getId()).isNotNull(); - } - - @Test - @DisplayName("회원 생성 실패 테스트 : 이메일") - void create_member_failBy_email_test() { - assertThatThrownBy(() -> Member.builder() - .password("qwer1234") - .phone("01012345678") - .gender(Gender.MALE) - .nickname("nikuname") - .name("parksey") - .loginType(LoginType.LOCAL) - .role(Role.USER) - .build()).isInstanceOf(MemberException.class); - } - - @Test - @DisplayName("회원 생성 실패 테스트 : 핸드폰") - void create_member_failBy_phone_test() { - assertThatThrownBy(() -> Member.builder() - .email("abc123@naver.com") - .password("qwer1234") - .gender(Gender.MALE) - .nickname("nikuname") - .name("parksey") - .loginType(LoginType.LOCAL) - .role(Role.USER) - .build()).isInstanceOf(MemberException.class); - } - - @Test - @DisplayName("회원 생성 실패 테스트 : 닉네임") - void create_member_failBy_nickName_test() { - assertThatThrownBy(() -> Member.builder() - .email("abc123@naver.com") - .password("qwer1234") - .phone("01012345678") - .gender(Gender.MALE) - .name("parksey") - .loginType(LoginType.LOCAL) - .role(Role.USER) - .build()).isInstanceOf(MemberException.class); - } - } -} diff --git a/module-domain/src/test/java/com/devtoon/jtoon/member/request/SignUpDtoTest.java b/module-domain/src/test/java/com/devtoon/jtoon/member/request/SignUpDtoTest.java deleted file mode 100644 index 172f88ea..00000000 --- a/module-domain/src/test/java/com/devtoon/jtoon/member/request/SignUpDtoTest.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.devtoon.jtoon.member.request; - -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; - -class SignUpDtoTest { - - @ParameterizedTest - @ValueSource(strings = { - "", - "123@naver.com", - "123", - "abc", - "@naver.com", - "abc@naver", - "abc@.com", - "abc@nav.c.c" - }) - @DisplayName("회원 생성 실패 테스트 : 이메일") - void create_memeber_failBy_email_test() { - - } -} diff --git a/module-domain/src/test/java/com/devtoon/jtoon/member/util/MemberRegExpTest.java b/module-domain/src/test/java/com/devtoon/jtoon/member/util/MemberRegExpTest.java deleted file mode 100644 index f894059f..00000000 --- a/module-domain/src/test/java/com/devtoon/jtoon/member/util/MemberRegExpTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.devtoon.jtoon.member.util; - -import static org.assertj.core.api.Assertions.*; - -import com.devtoon.jtoon.global.util.MemberRegExp; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; - -@DisplayName("회원 관련 정규식 표현 테스트") -class MemberRegExpTest { - - @Test - @DisplayName("이메일 정규식 성공 테스트") - void email_pattern_match_test() { - assertThat("abc123@naver.com").matches(MemberRegExp.EMAIL_PATTERN); - } - - @Test - @DisplayName("이메일 정규식 실패 테스트") - void email_pattern_fail_test() { - assertThat("abc123@naver").doesNotMatch(MemberRegExp.EMAIL_PATTERN); - } - - @Test - @DisplayName("핸드폰 번호 정규식 성공 테스트") - void phone_pattern_match_test() { - assertThat("01012345678").matches(MemberRegExp.PHONE_PATTERN); - } - - @Test - @DisplayName("핸드폰 번호 정규식 실패 테스트") - void phone_pattern_fail_test() { - assertThat("07012345678").doesNotMatch(MemberRegExp.PHONE_PATTERN); - } - - @Test - @DisplayName("비밀번호 정규식 성공 테스트") - void password_pattern_match_test() { - assertThat("Testing193!").matches(MemberRegExp.PASSWORD_PATTERN); - } - - @Test - @DisplayName("비밀번호 정규식 실패 테스트") - void password_pattern_fail_test() { - assertThat("testing193!").doesNotMatch(MemberRegExp.PASSWORD_PATTERN); - } -} diff --git a/module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java b/module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java deleted file mode 100644 index 9de178ad..00000000 --- a/module-domain/src/test/java/com/devtoon/jtoon/smtp/application/SmtpServiceTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.devtoon.jtoon.smtp.application; - -import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.test.context.SpringBootTest; - -@SpringBootTest -class SmtpServiceTest { - - @Autowired - SmtpService smtpService; - - @Test - void test_Email() { - smtpService.sendMail("parkseyeon99@naver.com", "123456"); - } -} \ No newline at end of file From 55c5c0e27dc6eeda25a0f7330490270087b07e8b Mon Sep 17 00:00:00 2001 From: ymkim97 Date: Mon, 4 Sep 2023 15:09:48 +0900 Subject: [PATCH 6/7] =?UTF-8?q?[JT-28]=20refactor:=20=EB=A6=AC=EB=B7=B0=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../member/presentation/MemberController.java | 15 ++++++------- module-domain/build.gradle | 1 - .../jtoon/global/config/MailConfig.java | 8 +++---- .../member/application/MemberService.java | 15 ++++++------- .../devtoon/jtoon/member/entity/Gender.java | 8 ++++--- .../jtoon/member/entity/LoginType.java | 5 +++-- .../devtoon/jtoon/member/entity/Member.java | 15 ++++++------- .../com/devtoon/jtoon/member/entity/Role.java | 3 ++- .../member/repository/MemberRepository.java | 2 ++ .../jtoon/member/request/SignUpDto.java | 4 ++-- .../jtoon/smtp/application/SmtpService.java | 1 - .../com/devtoon/jtoon/smtp/entity/Mail.java | 21 ++++++++++++------- .../config/WebSecurityConfiguration.java | 11 ++++++++++ 13 files changed, 64 insertions(+), 45 deletions(-) diff --git a/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java b/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java index dfbcf641..ee90f68b 100644 --- a/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java +++ b/module-application/src/main/java/com/devtoon/jtoon/member/presentation/MemberController.java @@ -1,12 +1,12 @@ package com.devtoon.jtoon.member.presentation; import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; 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.RequestParam; +import org.springframework.web.bind.annotation.ResponseStatus; import org.springframework.web.bind.annotation.RestController; import com.devtoon.jtoon.member.application.MemberService; @@ -22,16 +22,13 @@ public class MemberController { private final MemberService memberService; @PostMapping - public ResponseEntity signUp(@RequestBody @Valid SignUpDto signUpDto) { + @ResponseStatus(HttpStatus.CREATED) + public void signUp(@RequestBody @Valid SignUpDto signUpDto) { memberService.createMember(signUpDto); - - return new ResponseEntity<>(HttpStatus.CREATED); } - @GetMapping("/email-authorize") - public ResponseEntity authenticateEmail(@RequestParam(value = "email", required = true) String email) { - String authenticationUuid = memberService.sendEmailAuthentication(email); - - return ResponseEntity.status(HttpStatus.OK).body(authenticationUuid); + @GetMapping("/email-authorization") + public String authenticateEmail(@RequestParam(value = "email") String email) { + return memberService.sendEmailAuthentication(email); } } diff --git a/module-domain/build.gradle b/module-domain/build.gradle index 767c74d5..e8f8f865 100644 --- a/module-domain/build.gradle +++ b/module-domain/build.gradle @@ -13,7 +13,6 @@ dependencies { // SMTP implementation 'org.springframework.boot:spring-boot-starter-mail' - testImplementation 'com.icegreen:greenmail:2.1.0-alpha-2' // Security implementation 'org.springframework.boot:spring-boot-starter-security' diff --git a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java b/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java index 01d26d97..00ac2810 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java @@ -22,16 +22,14 @@ public class MailConfig { @Value("${smtp.port}") private Integer port; - + @Bean public JavaMailSender javaMailSender() { JavaMailSenderImpl javaMailSender = new JavaMailSenderImpl(); - javaMailSender.setHost(host); javaMailSender.setUsername(username); javaMailSender.setPassword(password); javaMailSender.setPort(port); - javaMailSender.setJavaMailProperties(getMailProperties()); return javaMailSender; @@ -43,7 +41,9 @@ private Properties getMailProperties() { properties.setProperty("mail.smtp.auth", "true"); properties.setProperty("mail.smtp.starttls.enable", "true"); properties.setProperty("mail.debug", "true"); - properties.setProperty("mail.smtp.ssl.trust","smtp.google.com"); + properties.setProperty("mail.smtp.ssl.trust","smtp.google.com"); + properties.setProperty("mail.smtp.ssl.protocols", "TLSv1.2"); + return properties; } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java b/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java index 496dfeea..87d2a3b2 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/application/MemberService.java @@ -25,17 +25,14 @@ public class MemberService { @Transactional public void createMember(SignUpDto signUpDto) { - isEmailExist(signUpDto.email()); - - String encryptedPassword = passwordEncoder.encode(signUpDto.password()); + validateDuplicateEmail(signUpDto.email()); + String encryptedPassword = encodePassword(signUpDto.password()); Member member = signUpDto.toEntity(encryptedPassword); - memberRepository.save(member); } public String sendEmailAuthentication(String email) { - isEmailExist(email); - + validateDuplicateEmail(email); UUID uuid = UUID.randomUUID(); String randomUuid = uuid.toString().substring(0, 6); Mail mail = Mail.createAuthentication(email, randomUuid); @@ -44,7 +41,11 @@ public String sendEmailAuthentication(String email) { return randomUuid; } - private void isEmailExist(String email) { + private String encodePassword(String password) { + return passwordEncoder.encode(password); + } + + private void validateDuplicateEmail(String email) { if (memberRepository.existsByEmail(email)) { throw new MemberException(ExceptionCode.MEMBER_EMAIL_CONFLICT); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java index e9e7f400..0a49e4cb 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Gender.java @@ -6,23 +6,25 @@ import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.AllArgsConstructor; @AllArgsConstructor(access = AccessLevel.PRIVATE) public enum Gender { - MALE, FEMALE; + MALE, + FEMALE; private static final Map GENDER_MAP; static { GENDER_MAP = Collections.unmodifiableMap( Arrays.stream(Gender.values()) - .collect(Collectors.toMap(Enum::name, gender -> gender))); + .collect(Collectors.toMap(Enum::name, Function.identity()))); } - public static Gender generate(String gender) { + public static Gender from(String gender) { return Optional.ofNullable(GENDER_MAP.get(gender)) .orElseThrow(() -> new MemberException(ExceptionCode.MEMBER_GENDER_INVALID_FORMAT)); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java index 303eac1d..9dc17eb4 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/LoginType.java @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.Map; import java.util.Optional; +import java.util.function.Function; import java.util.stream.Collectors; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -21,11 +22,11 @@ public enum LoginType { static { LOGIN_TYPE_MAP = Collections.unmodifiableMap( Arrays.stream(LoginType.values()) - .collect(Collectors.toMap(LoginType::name, loginType -> loginType)) + .collect(Collectors.toMap(LoginType::name, Function.identity())) ); } - public static LoginType generate(String loginType) { + public static LoginType from(String loginType) { return Optional.ofNullable(LOGIN_TYPE_MAP.get(loginType)) .orElseThrow(() -> new MemberException(ExceptionCode.MEMBER_LOGIN_TYPE_INVALID_FORMAT)); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java index cd61df8d..4abee474 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Member.java @@ -1,5 +1,7 @@ package com.devtoon.jtoon.member.entity; +import static java.util.Objects.*; + import com.devtoon.jtoon.exception.ExceptionCode; import com.devtoon.jtoon.global.common.BaseTimeEntity; import jakarta.persistence.Column; @@ -11,7 +13,6 @@ import jakarta.persistence.Id; import jakarta.persistence.Table; import java.time.LocalDateTime; -import java.util.Objects; import lombok.AccessLevel; import lombok.Builder; import lombok.Getter; @@ -65,12 +66,12 @@ public class Member extends BaseTimeEntity { @Builder private Member(String email, String password, String name, String nickname, Gender gender, String phone, Role role, LoginType loginType) { - this.email = Objects.requireNonNull(email, ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT.getMessage()); - this.password = Objects.requireNonNull(password, ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT.getMessage()); - this.name = Objects.requireNonNull(name, ExceptionCode.MEMBER_NAME_INVALID_FORMAT.getMessage()); - this.nickname = Objects.requireNonNull(nickname, ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT.getMessage()); - this.gender = Objects.requireNonNull(gender, ExceptionCode.MEMBER_GENDER_INVALID_FORMAT.getMessage()); - this.phone = Objects.requireNonNull(phone, ExceptionCode.MEMBER_PHONE_INVALID_FORMAT.getMessage()); + this.email = requireNonNull(email, ExceptionCode.MEMBER_EMAIL_INVALID_FORMAT.getMessage()); + this.password = requireNonNull(password, ExceptionCode.MEMBER_PASSWORD_INVALID_FORMAT.getMessage()); + this.name = requireNonNull(name, ExceptionCode.MEMBER_NAME_INVALID_FORMAT.getMessage()); + this.nickname = requireNonNull(nickname, ExceptionCode.MEMBER_NICKNAME_INVALID_FORMAT.getMessage()); + this.gender = requireNonNull(gender, ExceptionCode.MEMBER_GENDER_INVALID_FORMAT.getMessage()); + this.phone = requireNonNull(phone, ExceptionCode.MEMBER_PHONE_INVALID_FORMAT.getMessage()); this.role = role; this.loginType = loginType; } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java index e9828b96..153c54d1 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/entity/Role.java @@ -5,5 +5,6 @@ @AllArgsConstructor(access = AccessLevel.PRIVATE) public enum Role { - USER, ADMIN + USER, + ADMIN } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java b/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java index b26b5125..4bf13bf8 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/repository/MemberRepository.java @@ -3,7 +3,9 @@ import org.springframework.data.jpa.repository.JpaRepository; import com.devtoon.jtoon.member.entity.Member; +import java.util.Optional; public interface MemberRepository extends JpaRepository { boolean existsByEmail(String email); + Optional findByPhone(String phone); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java b/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java index cf01446f..3cf58d70 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/member/request/SignUpDto.java @@ -27,10 +27,10 @@ public Member toEntity(String encryptedPassword) { .password(encryptedPassword) .name(name) .nickname(nickname) - .gender(Gender.generate(gender)) + .gender(Gender.from(gender)) .phone(phone) .role(Role.USER) - .loginType(LoginType.generate(loginType)) + .loginType(LoginType.from(loginType)) .build(); } } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java index 633fa91f..a6a8ec1b 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java @@ -27,7 +27,6 @@ public void sendMail(Mail mail) { mimeMessageHelper.setSubject(mail.getSubject()); mimeMessageHelper.setText(mail.getText()); javaMailSender.send(mimeMessage); - } catch (MessagingException | MailException e) { throw new MemberException(ExceptionCode.MEMBER_MESSAGE_SEND_FAILED); } diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java b/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java index 38a22a41..be9d42da 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java +++ b/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java @@ -1,5 +1,6 @@ package com.devtoon.jtoon.smtp.entity; +import lombok.Builder; import lombok.Getter; @Getter @@ -11,21 +12,25 @@ public class Mail { private String to; private String text; - private Mail(String to, String text) { - this.to = to; - this.text = text; - } - + @Builder private Mail(String subject, String to, String text) { - this(to, text); this.subject = subject; + this.to = to; + this.text = text; } public static Mail createEvent(String subject, String to, String text) { - return new Mail(subject, to, text); + return Mail.builder() + .subject(subject) + .to(to) + .text(text) + .build(); } public static Mail createAuthentication(String to, String text) { - return new Mail(to, text); + return Mail.builder() + .to(to) + .text(text) + .build(); } } diff --git a/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java b/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java index c28e57dd..d0ff6dbd 100644 --- a/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java +++ b/module-internal/src/main/java/com/devtoon/jtoon/security/config/WebSecurityConfiguration.java @@ -2,9 +2,11 @@ import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.SecurityFilterChain; @Configuration @EnableWebSecurity @@ -14,4 +16,13 @@ public class WebSecurityConfiguration { public PasswordEncoder encoder() { return new BCryptPasswordEncoder(); } + + @Bean + public SecurityFilterChain securityFilterChain (HttpSecurity http) throws Exception { + http + .authorizeHttpRequests(request -> request + .anyRequest().permitAll()) + ; + return http.build(); + } } From 7f88c6cd7225b7f3bd2c2b64cbeca21e87457089 Mon Sep 17 00:00:00 2001 From: ymkim97 Date: Mon, 4 Sep 2023 15:22:23 +0900 Subject: [PATCH 7/7] =?UTF-8?q?[JT-28]=20refactor:=20SMTP=20=EC=9D=B8?= =?UTF-8?q?=ED=94=84=EB=9D=BC=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 15 +++++++++++++-- module-domain-smtp/build.gradle | 4 ++++ .../jtoon/smtp/application/SmtpService.java | 0 .../devtoon/jtoon/smtp}/config/MailConfig.java | 2 +- .../java/com/devtoon/jtoon/smtp/entity/Mail.java | 0 module-domain/build.gradle | 4 +--- settings.gradle | 2 +- 7 files changed, 20 insertions(+), 7 deletions(-) create mode 100644 module-domain-smtp/build.gradle rename {module-domain => module-domain-smtp}/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java (100%) rename {module-domain/src/main/java/com/devtoon/jtoon/global => module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp}/config/MailConfig.java (97%) rename {module-domain => module-domain-smtp}/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java (100%) diff --git a/build.gradle b/build.gradle index 324b2461..9e29f224 100644 --- a/build.gradle +++ b/build.gradle @@ -40,9 +40,10 @@ subprojects { project(':module-application') { dependencies { - implementation project(':module-core') - implementation project(':module-domain-s3') implementation project(':module-domain') + implementation project(':module-domain-s3') + implementation project(':module-domain-smtp') + implementation project(':module-core') } } @@ -51,6 +52,7 @@ project(':module-domain') { dependencies { implementation project(':module-core') + implementation project(':module-domain-smtp') implementation project(':module-internal') } } @@ -63,6 +65,15 @@ project(':module-domain-s3') { } } +project(':module-domain-smtp') { + bootJar.enabled = false + + dependencies { + implementation project(':module-core') + implementation project(':module-internal') + } +} + project(':module-internal') { bootJar.enabled = false diff --git a/module-domain-smtp/build.gradle b/module-domain-smtp/build.gradle new file mode 100644 index 00000000..6c1f2c7c --- /dev/null +++ b/module-domain-smtp/build.gradle @@ -0,0 +1,4 @@ +dependencies { + // SMTP + implementation 'org.springframework.boot:spring-boot-starter-mail' +} diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java b/module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java similarity index 100% rename from module-domain/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java rename to module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/application/SmtpService.java diff --git a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java b/module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/config/MailConfig.java similarity index 97% rename from module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java rename to module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/config/MailConfig.java index 00ac2810..339a1257 100644 --- a/module-domain/src/main/java/com/devtoon/jtoon/global/config/MailConfig.java +++ b/module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/config/MailConfig.java @@ -1,4 +1,4 @@ -package com.devtoon.jtoon.global.config; +package com.devtoon.jtoon.smtp.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; diff --git a/module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java b/module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java similarity index 100% rename from module-domain/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java rename to module-domain-smtp/src/main/java/com/devtoon/jtoon/smtp/entity/Mail.java diff --git a/module-domain/build.gradle b/module-domain/build.gradle index e8f8f865..46b573ed 100644 --- a/module-domain/build.gradle +++ b/module-domain/build.gradle @@ -1,6 +1,7 @@ dependencies { // JPA implementation 'org.springframework.boot:spring-boot-starter-data-jpa' + implementation project(path: ':module-domain-smtp') // Test testImplementation 'org.springframework.boot:spring-boot-starter-test' @@ -11,9 +12,6 @@ dependencies { // Bean Validation implementation 'org.springframework.boot:spring-boot-starter-validation' - // SMTP - implementation 'org.springframework.boot:spring-boot-starter-mail' - // Security implementation 'org.springframework.boot:spring-boot-starter-security' } diff --git a/settings.gradle b/settings.gradle index 02e7e75f..14af9a9e 100644 --- a/settings.gradle +++ b/settings.gradle @@ -2,6 +2,6 @@ rootProject.name = 'jtoon' include 'module-application' include 'module-domain' include 'module-domain-s3' +include 'module-domain-smtp' include 'module-internal' include 'module-core' -