diff --git a/src/main/java/com/t3t/frontserver/auth/controller/LoginController.java b/src/main/java/com/t3t/frontserver/auth/controller/LoginController.java index 91cc62f..4727a45 100644 --- a/src/main/java/com/t3t/frontserver/auth/controller/LoginController.java +++ b/src/main/java/com/t3t/frontserver/auth/controller/LoginController.java @@ -5,8 +5,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.t3t.frontserver.auth.model.request.LoginRequestDto; import com.t3t.frontserver.auth.service.LoginService; +import com.t3t.frontserver.member.model.constant.MemberStatus; +import com.t3t.frontserver.member.model.response.MemberInfoResponse; +import com.t3t.frontserver.member.service.MemberService; import feign.FeignException; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpHeaders; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; @@ -26,24 +30,29 @@ import java.util.Base64; import java.util.Map; - +@Slf4j @Controller @RequiredArgsConstructor public class LoginController { private final LoginService loginService; + private final MemberService memberService; + + /** * 로그인 페이지 뷰 반환 + * * @return 로그인 페이지 뷰 * @author joohyun1996(이주현) */ @GetMapping("/login") - public String loginPage(Model model){ + public String loginPage(Model model) { model.addAttribute("loginRequestDto", new LoginRequestDto()); return "main/page/login"; } /** * 로그인 요청 처리 + * * @param loginRequestDto,redirectAttributes,resp * @return 성공시 : redirect:/, 실패시 : redirect:/login * @throws JsonProcessingException @@ -51,18 +60,28 @@ public String loginPage(Model model){ */ @PostMapping("/login") public String doLogin(@ModelAttribute @Valid LoginRequestDto loginRequestDto, - RedirectAttributes redirectAttributes, - HttpServletResponse resp) throws JsonProcessingException { + RedirectAttributes redirectAttributes, + Model model, + HttpServletResponse resp) throws JsonProcessingException { try { ResponseEntity responseEntity = loginService.login(loginRequestDto); String access = responseEntity.getHeaders().getFirst(HttpHeaders.AUTHORIZATION).trim().split(" ")[1]; + MemberInfoResponse memberInfoResponse = memberService.getMemberInfoResponseById(getMemberId(access)); + + if (memberInfoResponse.getStatus().equals(MemberStatus.INACTIVE)) { + model.addAttribute("memberId", memberInfoResponse.getMemberId()); + model.addAttribute("memberLatestLogin", memberInfoResponse.getLatestLogin()); + model.addAttribute("memberName", memberInfoResponse.getName()); + return "main/page/activateMemberIssue"; + } + Cookie cookie = new Cookie("t3t", access); cookie.setHttpOnly(true); cookie.setMaxAge(-1); resp.addCookie(cookie); - + // contextholder에 추가 SecurityContextHolder.getContext().setAuthentication(getAuthentication(access)); @@ -75,6 +94,7 @@ public String doLogin(@ModelAttribute @Valid LoginRequestDto loginRequestDto, /** * Security Context Holder를 사용하기 위해 임의의 CustomUserDetails를 넣고 반환해주는 메소드 + * * @param token * @return Authentication * @throws JsonProcessingException @@ -92,4 +112,15 @@ public UsernamePasswordAuthenticationToken getAuthentication(String token) throw UserDetails userDetails = User.withUsername(member).password("").roles(role).build(); return new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); } + + public long getMemberId(String token) throws JsonProcessingException { + byte[] decodedPayload = Base64.getDecoder().decode(token.split("\\.")[1]); + ObjectMapper objectMapper = new ObjectMapper(); + Map map = objectMapper.readValue(new String(decodedPayload), + new TypeReference>() { + }); + + log.info("memberId : {}", map.get("username")); + return Long.parseLong(map.get("username").toString()); + } } diff --git a/src/main/java/com/t3t/frontserver/member/adaptor/MemberAdaptor.java b/src/main/java/com/t3t/frontserver/member/adaptor/MemberAdaptor.java index 72e6d9b..d4cfd30 100644 --- a/src/main/java/com/t3t/frontserver/member/adaptor/MemberAdaptor.java +++ b/src/main/java/com/t3t/frontserver/member/adaptor/MemberAdaptor.java @@ -100,4 +100,32 @@ public void withdrawMember(long memberId) { } } + /** + * 회원 휴면 계정 활성화 코드 발급 + * + * @param memberId 대상 회원 식별자 + * @author woody35545(구건모) + */ + public void issueMemberActivationCode(long memberId) { + try { + memberApiClient.issueMemberActivationCertCode(memberId); + } catch (FeignException e) { + throw new MemberApiClientException("회원 활성화 코드 발급에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); + } + } + + /** + * 회원 휴면 계정 활성화 코드 검증 + * + * @param memberId 대상 회원 식별자 + * @param code 인증 코드 + * @author woody35545(구건모) + */ + public void verifyMemberActivationCode(long memberId, String code) { + try { + memberApiClient.verifyMemberActivationCertCode(memberId, code); + } catch (FeignException e) { + throw new MemberApiClientException("회원 활성화 코드 검증에 실패하였습니다. " + FeignClientUtils.getMessageFromFeignException(e)); + } + } } diff --git a/src/main/java/com/t3t/frontserver/member/client/MemberApiClient.java b/src/main/java/com/t3t/frontserver/member/client/MemberApiClient.java index 738107d..a75fce9 100644 --- a/src/main/java/com/t3t/frontserver/member/client/MemberApiClient.java +++ b/src/main/java/com/t3t/frontserver/member/client/MemberApiClient.java @@ -60,9 +60,27 @@ public interface MemberApiClient { /** * 회원 탈퇴 API + * * @param memberId 탈퇴할 회원 식별자 * @author woody35545(구건모) */ @DeleteMapping("/t3t/bookstore/members/{memberId}") BaseResponse withdrawMember(@PathVariable("memberId") long memberId); + + /** + * 회원 휴면 계정 활성화 인증 코드 발급 API + * + * @author wooody35545(구건모) + */ + @PostMapping("/t3t/bookstore/members/{memberId}/codes?type=issue") + BaseResponse issueMemberActivationCertCode(@PathVariable("memberId") Long memberId); + + /** + * 회원 휴면 계정 활성화 인증 코드 검증 API + * + * @author wooody35545(구건모) + */ + @PostMapping("/t3t/bookstore/members/{memberId}/codes?type=verify") + BaseResponse verifyMemberActivationCertCode(@PathVariable("memberId") Long memberId, @RequestParam("value") String code); + } diff --git a/src/main/java/com/t3t/frontserver/member/controller/MemberController.java b/src/main/java/com/t3t/frontserver/member/controller/MemberController.java index 699eaa8..b63e4fd 100644 --- a/src/main/java/com/t3t/frontserver/member/controller/MemberController.java +++ b/src/main/java/com/t3t/frontserver/member/controller/MemberController.java @@ -104,4 +104,40 @@ public String deleteMember(RedirectAttributes redirectAttributes, HttpServletRes return "redirect:/message"; } + + /** + * 휴면 회원 활성화 인증 코드 발급 + * @author woody35545(구건모) + */ + @PostMapping("/member/activation/issue") + public String issueMemberActivationCertCode(@RequestParam("memberId") long memberId, + @RequestParam("memberLatestLogin") String memberLatestLogin, + @RequestParam("memberName") String memberName, + Model model) { + memberService.issueMemberActivationCode(memberId); + + model.addAttribute("memberLatestLogin", memberLatestLogin); + model.addAttribute("memberId", memberId); + model.addAttribute("memberName", memberName); + + return "main/page/activateMemberVerify"; + } + + /** + * 휴면 회원 활성화 인증 코드 검증 + * + * @param memberId 회원 식별자 + * @param code 인증 코드 + * @author woody35545(구건모) + */ + @PostMapping("/member/activation/verify") + public String verifyMemberActivationCertCode(@RequestParam("memberId") long memberId, + @RequestParam("activationCode") String code, + RedirectAttributes redirectAttributes) { + + memberService.verifyMemberActivationCode(memberId, code); + + redirectAttributes.addAttribute("message", "회원 활성화가 완료되었습니다. 다시 로그인 해주세요."); + return "redirect:/message"; + } } diff --git a/src/main/java/com/t3t/frontserver/member/service/MemberService.java b/src/main/java/com/t3t/frontserver/member/service/MemberService.java index 41703bd..5572c11 100644 --- a/src/main/java/com/t3t/frontserver/member/service/MemberService.java +++ b/src/main/java/com/t3t/frontserver/member/service/MemberService.java @@ -13,7 +13,6 @@ import java.util.List; -@Slf4j @Service @RequiredArgsConstructor public class MemberService { @@ -72,4 +71,25 @@ public void modifyPassword(long memberId, MemberPasswordModifyRequest request) { public void withdrawMember(long memberId) { memberAdaptor.withdrawMember(memberId); } + + /** + * 휴면 회원 활성화 인증 코드 발급 + * + * @param memberId 회원 식별자 + * @author woody35545(구건모) + */ + public void issueMemberActivationCode(long memberId) { + memberAdaptor.issueMemberActivationCode(memberId); + } + + /** + * 휴면 회원 활성화 인증 코드 검증 + * + * @param memberId 회원 식별자 + * @param activationCode 활성화 코드 + * @author woody35545(구건모) + */ + public void verifyMemberActivationCode(long memberId, String activationCode) { + memberAdaptor.verifyMemberActivationCode(memberId, activationCode); + } } diff --git a/src/main/resources/templates/main/page/activateMemberIssue.html b/src/main/resources/templates/main/page/activateMemberIssue.html new file mode 100644 index 0000000..76fe24f --- /dev/null +++ b/src/main/resources/templates/main/page/activateMemberIssue.html @@ -0,0 +1,27 @@ + + + +
+

휴면 계정 안내

+

회원님의 계정은 3개월 이상 로그인하지 않아서 휴면 처리되었습니다.

+ + + +

계속 서비스를 이용하시려면 [휴면 해제하기] 를 눌러 휴면 해제를 진행해주세요.

+ +
+
+ + + + + +
+
+ +
+
\ No newline at end of file diff --git a/src/main/resources/templates/main/page/activateMemberVerify.html b/src/main/resources/templates/main/page/activateMemberVerify.html new file mode 100644 index 0000000..e6b7842 --- /dev/null +++ b/src/main/resources/templates/main/page/activateMemberVerify.html @@ -0,0 +1,65 @@ + + + + +
+

휴면 계정 안내

+

회원님의 계정은 3개월 이상 로그인하지 않아서 휴면 처리되었습니다.

+ + + +

인증 번호가 발송되었습니다. 인증 번호를 입력 후 [휴면 해제하기] 를 눌러 휴면 해제를 완료해주세요.

+ +
+
+
+ + + + +
+
+
+ +
+ + +
+ \ No newline at end of file