package com.pollex.pam.web.rest; import java.util.Arrays; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import com.pollex.pam.business.aop.logging.audit.AuditLoggingInject; import com.pollex.pam.business.domain.Consultant; import com.pollex.pam.business.security.token.EServiceAuthenticationToken; import com.pollex.pam.business.service.ConsultantService; import com.pollex.pam.business.web.vm.EServiceLoginVM; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.PathVariable; 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; import com.pollex.pam.config.ApplicationProperties; import com.pollex.pam.business.domain.Customer; import com.pollex.pam.business.enums.OtpLoginTypeEnum; import com.pollex.pam.business.repository.CustomerRepository; import com.pollex.pam.security.jwt.JWTFilter; import com.pollex.pam.security.jwt.TokenProvider; import com.pollex.pam.service.CustomerAuthService; import com.pollex.pam.service.CustomerService; import com.pollex.pam.business.service.OtpTmpService; import com.pollex.pam.service.OtpUtilService; import com.pollex.pam.service.OtpWebService; import com.pollex.pam.business.service.dto.CustomerRegisterDTO; import com.pollex.pam.business.service.dto.OtpResponseDTO; import com.pollex.pam.business.web.errors.OtpLoginFailException; import com.pollex.pam.business.web.vm.OtpLoginVM; import com.pollex.pam.business.web.vm.VerifyOtpVM; import static com.pollex.pam.business.aop.logging.audit.AuditLoggingType.CONSULTANT_LOGIN; import static com.pollex.pam.business.aop.logging.audit.AuditLoggingType.CUSTOMER_LOGIN; @RestController @RequestMapping("/api/otp") public class OtpResource { private final static Logger log = LoggerFactory.getLogger(OtpResource.class); @Autowired ApplicationProperties applicationProperty; @Autowired OtpWebService otpWebService; @Autowired AuthenticationManagerBuilder authenticationManagerBuilder; @Autowired TokenProvider tokenProvider; @Autowired CustomerAuthService customerAuthService; @Autowired OtpTmpService otpTmpService; @Autowired CustomerService customerService; @Autowired OtpUtilService otpUtilService; @Autowired CustomerRepository customerRepository; @Autowired ConsultantService consultantService; @PostMapping("/sendOtp/{imgCode}") public ResponseEntity sendOtp(@RequestBody OtpLoginVM login , @PathVariable String imgCode, HttpServletRequest request) { HttpSession session = request.getSession(); String sessionImpCode = (String) session.getAttribute("img_code"); if (!StringUtils.hasText(sessionImpCode) || !StringUtils.hasText(imgCode)) { throw new OtpLoginFailException("驗證碼輸入錯誤"); } if(!imgCode.equals(sessionImpCode)) { throw new OtpLoginFailException("驗證碼輸入錯誤"); } session.setAttribute("img_code", null); OtpResponseDTO otpResponse; if(applicationProperty.isMockLogin()) { otpResponse = getMockSendOtpResponse(); }else if(login.getLoginType() == OtpLoginTypeEnum.SMS) { otpResponse = otpWebService.sendByPhone(login.getAccount()); } else if(login.getLoginType() == OtpLoginTypeEnum.EMAIL) { otpResponse = otpWebService.sendByEmail(login.getAccount()); }else { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("can not support this login type, loginType = " + login.getLoginType().name()); } otpTmpService.createOtpTmp(login.getAccount(), otpResponse.getIndexKey()); return new ResponseEntity<>(otpResponse, HttpStatus.OK); } @AuditLoggingInject(type = CUSTOMER_LOGIN) @PostMapping("/verify") public ResponseEntity verifyOtp(@RequestBody VerifyOtpVM verifyOtpParam ) { otpUtilService.verifyOtp(verifyOtpParam); Customer customer = customerRepository .findOneByEmailEqualsOrPhoneEquals(verifyOtpParam.getAccount()) .orElse(null); if (customer == null) { return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); } String jwt = customerAuthService.authorize(customer, verifyOtpParam.getIndexKey(), verifyOtpParam.getOtpCode()); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); } private OtpResponseDTO getMockSendOtpResponse() { String indexKey = UUID.randomUUID().toString().substring(0, 8); return new OtpResponseDTO(Arrays.asList(indexKey, "0", "", "")); } @PostMapping("/register") public ResponseEntity registerAccount(@RequestBody CustomerRegisterDTO registDTO) { Customer account = customerService.registerCustomer(registDTO); String jwt = customerAuthService.authorize(account, registDTO.getIndexKey(), registDTO.getOtpCode()); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); } @PostMapping("/consultant/sendOtp/{login}") public ResponseEntity consultantSendOtp(@PathVariable String login) { Consultant consultant = consultantService.findByAgentNo(login); OtpResponseDTO otpResponse; if(applicationProperty.isMockLogin()) { otpResponse = getMockSendOtpResponse(); }else if(StringUtils.hasText(consultant.getPhoneNumber())) { otpResponse = otpWebService.sendByPhone(consultant.getPhoneNumber()); }else if(StringUtils.hasText(consultant.getEmail())) { otpResponse = otpWebService.sendByEmail(consultant.getEmail()); }else { return ResponseEntity.status(HttpStatus.BAD_REQUEST).body("can not find phone and email to send otp, loginType = " + login); } otpTmpService.createOtpTmp(login, otpResponse.getIndexKey()); return new ResponseEntity<>(otpResponse, HttpStatus.OK); } @PostMapping("/consultant/verifyOtp") public ResponseEntity consultantVerifyOtp(@RequestBody VerifyOtpVM verifyOtpParam , HttpServletRequest request) { HttpSession session = request.getSession(); Authentication authentication = (Authentication) session.getAttribute("authentication"); String authAccount = authentication.getPrincipal().toString(); if(!authAccount.equals(verifyOtpParam.getAccount())){ return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build(); } otpUtilService.verifyOtp(verifyOtpParam); Consultant consultant = consultantService.findByAgentNo(verifyOtpParam.getAccount()); if (consultant == null) { return ResponseEntity.status(HttpStatus.FORBIDDEN).build(); } consultantService.updateLoginTime(verifyOtpParam.getAccount()); SecurityContextHolder.getContext().setAuthentication(authentication); String jwt = tokenProvider.createToken(authentication, false); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); session.setAttribute("authentication", null); return new ResponseEntity<>(new UserJWTController.JWTToken(jwt), httpHeaders, HttpStatus.OK); } }