Skip to content

Commit

Permalink
Merge pull request Kernel360#156 from cgk95/feat/Kernel360#154
Browse files Browse the repository at this point in the history
Feature : 가입시 입력한 이메일로 분실한 회원 아이디를 발송하는 기능
  • Loading branch information
chan99k authored Feb 19, 2024
2 parents abc85e6 + ec87f6a commit 65b95ea
Show file tree
Hide file tree
Showing 14 changed files with 156 additions and 25 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/cicd-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ jobs:
spring.datasource.password: ${{ secrets.DB_PW }}
external.ecolife-api.path: ${{ secrets.ECOLIFE_PATH }}
external.ecolife-api.service-key: ${{ secrets.ECOLIFE_KEY }}
spring.mail.username: ${{ secrets.SMTP_GOOGLE_EMAIL }}
spring.mail.password: ${{ secrets.SMTP_PASSWORD }}

- name: Grant execute permission And Build with Gradle (api)
working-directory: ./module-api
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/cicd-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ jobs:
spring.datasource.url: ${{ secrets.DB_URL_AWS }}
spring.datasource.username: ${{ secrets.DB_USER }}
spring.datasource.password: ${{ secrets.DB_PW }}
spring.mail.username: ${{ secrets.SMTP_GOOGLE_EMAIL }}
spring.mail.password: ${{ secrets.SMTP_PASSWORD }}

- name: Grant execute permission And Build with Gradle (api)
working-directory: ./module-api
Expand Down
1 change: 1 addition & 0 deletions module-api/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ dependencies {
implementation 'org.springframework.boot:spring-boot-starter-aop'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
//implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.springframework.boot:spring-boot-starter-mail'

// jasypt
implementation 'com.github.ulisesbocchio:jasypt-spring-boot-starter:3.0.5'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ public enum MemberBusinessCode implements BusinessCode {
SUCCESS_REQUEST_CHANGE_PASSWORD_MEMBER(HttpStatus.OK.value(), "BMC007", "비밀번호가 변경 되었습니다."),
SUCCESS_VALIDATE_PASSWORD_MEMBER(HttpStatus.OK.value(), "BMC008", "비밀번호가 확인 되었습니다."),
SUCCESS_REQUEST_UPDATE_WASH_INFO_MEMBER(HttpStatus.OK.value(), "BMC009", "WashInfo 정보가 변경 되었습니다."),
SUCCESS_REQUEST_UPDATE_CAR_INFO_MEMBER(HttpStatus.OK.value(), "BMC010", "CarInfo 정보가 변경 되었습니다.");
SUCCESS_REQUEST_UPDATE_CAR_INFO_MEMBER(HttpStatus.OK.value(), "BMC010", "CarInfo 정보가 변경 되었습니다."),
SUCCESS_REQUEST_FIND_MEMBER_ID(HttpStatus.OK.value(), "BMC011","회원 아이디 찾기 메일이 발송되었습니다.");


private final int status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,14 @@


import com.kernel360.carinfo.entity.CarInfo;
import com.kernel360.exception.BusinessException;
import com.kernel360.member.code.MemberBusinessCode;
import com.kernel360.member.code.MemberErrorCode;
import com.kernel360.member.dto.CarInfoDto;
import com.kernel360.member.dto.FindMemberIdFromEmailDto;
import com.kernel360.member.dto.MemberDto;
import com.kernel360.member.dto.WashInfoDto;
import com.kernel360.member.service.FindService;
import com.kernel360.member.service.MemberService;
import com.kernel360.response.ApiResponse;
import com.kernel360.washinfo.entity.WashInfo;
Expand All @@ -25,6 +29,8 @@ public class MemberController {

private final MemberService memberService;

private final FindService findService;

@PostMapping("/join")
public ResponseEntity<ApiResponse<Object>> joinMember(@RequestBody MemberDto joinRequestDto) {

Expand Down Expand Up @@ -75,5 +81,17 @@ public ResponseEntity<ApiResponse<CarInfo>> saveCarInfo(@RequestBody CarInfoDto
return ApiResponse.toResponseEntity(MemberBusinessCode.SUCCESS_REQUEST_UPDATE_CAR_INFO_MEMBER);
}

@PostMapping("/find/memberId")
public ResponseEntity<ApiResponse<Object>> sendMemberIdByEmail(@RequestBody FindMemberIdFromEmailDto dto) {
String memberId = memberService.findByEmail(dto.email()).id();

if (memberId.isEmpty()) {
throw new BusinessException(MemberErrorCode.FAILED_FIND_MEMBER_INFO);
}

findService.sendMemberId(dto.email(), memberId);

return ApiResponse.toResponseEntity(
MemberBusinessCode.SUCCESS_REQUEST_FIND_MEMBER_ID); // 아이디는 이메일로 보내고, 외부 노출 X
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.kernel360.member.dto;

public record FindMemberIdFromEmailDto(String email) {
public static FindMemberIdFromEmailDto of(String email) {
return new FindMemberIdFromEmailDto(email);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package com.kernel360.member.service;

public interface EmailSender {
void sendMemberId(String email, String memberId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.kernel360.member.service;

import lombok.RequiredArgsConstructor;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

@Service
@RequiredArgsConstructor
public class FindService implements EmailSender {

private final JavaMailSender mailSender;

public void sendMemberId(String email, String memberId) {
new Thread(() -> mailSender.send(mimeMessage -> {
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);
mimeMessageHelper.setTo(email);
mimeMessageHelper.setSubject("Wash-Fit 아이디/패스워드 찾기");
String textContent = "가입하신 아이디는 " + "'" + memberId + "' 입니다.";
mimeMessageHelper.setText(textContent);
})).start();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -220,5 +220,12 @@ public void saveCarInfo(CarInfoDto carInfoDto, String token) {
carInfoRepository.save(carInfo);
}

public MemberDto findByEmail(String email) {
Member member = memberRepository.findOneByEmail(email);
if (member == null) {
throw new BusinessException(MemberErrorCode.FAILED_FIND_MEMBER_INFO);
}

return MemberDto.from(member);
}
}
14 changes: 14 additions & 0 deletions module-api/src/main/resources/application-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

mail:
host: smtp.gmail.com
username: ${SMTP_GOOGLE_EMAIL}
password: ${SMTP_PASSWORD}
port: 587
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
starttls:
enable: true
timeout: 5000
writetimeout: 5000
logging:
file:
path: ./logs/api/
Expand Down
14 changes: 14 additions & 0 deletions module-api/src/main/resources/application-local.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

mail:
host: smtp.gmail.com
username: ENC(TEY+McqfBOprewh0EpDJIclJKk8o+bY/0CWpPynWeylc/HNeWGSI6Q==)
password: ENC(gAVZp58ZhI0MCJcvKFhB0lVNYPtMg35QIslSCJhu2pJB4ck+w1vscA==)
port: 587
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
starttls:
enable: true
timeout: 5000
writetimeout: 5000
jasypt:
encryptor:
algorithm: PBEWithMD5AndTripleDES
Expand Down
15 changes: 15 additions & 0 deletions module-api/src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ spring:
autoconfigure:
exclude: org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration

mail:
host: smtp.gmail.com
username: ${SMTP_GOOGLE_EMAIL}
password: ${SMTP_PASSWORD}
port: 587
properties:
mail:
smtp:
auth: true
connectiontimeout: 5000
starttls:
enable: true
timeout: 5000
writetimeout: 5000

logging:
file:
path: ./logs/api/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.kernel360.main.controller.MainContoller;
import com.kernel360.main.service.MainService;
import com.kernel360.member.controller.MemberController;
import com.kernel360.member.service.FindService;
import com.kernel360.member.service.MemberService;
import com.kernel360.mypage.controller.MyPageController;
import com.kernel360.product.controller.ProductController;
Expand Down Expand Up @@ -47,4 +48,7 @@ public abstract class ControllerTest {

@MockBean
protected MainService mainService;

@MockBean
protected FindService findService;
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
package com.kernel360.member.controller;

import static org.mockito.BDDMockito.given;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.kernel360.common.ControllerTest;
import com.kernel360.member.dto.FindMemberIdFromEmailDto;
import com.kernel360.member.dto.MemberDto;
import java.time.LocalDate;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;

import java.time.LocalDate;

import static org.mockito.BDDMockito.given;


class MemberControllerTest extends ControllerTest {

Expand All @@ -21,7 +21,7 @@ class MemberControllerTest extends ControllerTest {
void 회원입요청() throws Exception {

/** given 목데이터 세팅 **/
MemberDto memberDto = MemberDto.of("testID", "[email protected]", "testPassword", "man","30");
MemberDto memberDto = MemberDto.of("testID", "[email protected]", "testPassword", "man", "30");

ObjectMapper objectMapper = new ObjectMapper();
String param = objectMapper.writeValueAsString(memberDto);
Expand All @@ -30,8 +30,8 @@ class MemberControllerTest extends ControllerTest {
mockMvc.perform(MockMvcRequestBuilders.post("/member/join") //이 다음 restful
.contentType(MediaType.APPLICATION_JSON)
.content(param))
.andExpect(MockMvcResultMatchers.status().isCreated()) //기대 결과 상태값
.andReturn();
.andExpect(MockMvcResultMatchers.status().isCreated()) //기대 결과 상태값
.andReturn();
}

@Test
Expand All @@ -40,17 +40,17 @@ class MemberControllerTest extends ControllerTest {

MemberDto memberDto = MemberDto.of("testID", "testPassword");
MemberDto memberInfo = new MemberDto(1L,
"test01",
"[email protected]",
"",
null,
null,
LocalDate.now(),
"test01",
null,
null,
"dummyToken"
);
"test01",
"[email protected]",
"",
null,
null,
LocalDate.now(),
"test01",
null,
null,
"dummyToken"
);
ObjectMapper objectMapper = new ObjectMapper();
String param = objectMapper.writeValueAsString(memberDto);

Expand All @@ -60,8 +60,8 @@ class MemberControllerTest extends ControllerTest {
mockMvc.perform(MockMvcRequestBuilders.post("/member/login")
.contentType(MediaType.APPLICATION_JSON)
.content(param))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();

}

Expand All @@ -77,8 +77,8 @@ class MemberControllerTest extends ControllerTest {
mockMvc.perform(MockMvcRequestBuilders.get("/member/duplicatedCheckId/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.content(message))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
}

@Test
Expand All @@ -93,9 +93,27 @@ class MemberControllerTest extends ControllerTest {
mockMvc.perform(MockMvcRequestBuilders.get("/member/duplicatedCheckEmail/{email}", email)
.contentType(MediaType.APPLICATION_JSON)
.content(message))
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
.andExpect(MockMvcResultMatchers.status().isOk())
.andReturn();
}


@Test
@DisplayName("이메일을 입력 받아 아이디 찾기 이메일 발송")
void 아이디_찾기_이메일_발송_검사() throws Exception {
/** given 목데이터 세팅 **/
FindMemberIdFromEmailDto dto = FindMemberIdFromEmailDto.of("[email protected]");
MemberDto memberDto = MemberDto.of("testMemberId", "testPassword001");

given(memberService.findByEmail(dto.email())).willReturn(memberDto);

ObjectMapper objectMapper = new ObjectMapper();
String dtoAsString = objectMapper.writeValueAsString(dto);

/** then **/
mockMvc.perform(MockMvcRequestBuilders.post("/member/find/memberId")
.contentType(MediaType.APPLICATION_JSON)
.content(dtoAsString))
.andExpect(MockMvcResultMatchers.status().isOk()).andReturn();
}
}

0 comments on commit 65b95ea

Please sign in to comment.