이메일 인증 재발송 기능 제거 및 관련 코드 정리
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled

- `emailResendPopup` 및 팝업 호출 로직 삭제
- `InquiryAdminNotifier` → `CommunityAdminNotifier`로 클래스 명칭 변경
- 제휴 신청 시 관리자 알림 로직 추가
This commit is contained in:
Rinjae
2026-06-24 19:45:37 +09:00
parent 6f776ed72a
commit f79e528fec
14 changed files with 32 additions and 151 deletions
+1
View File
@@ -170,6 +170,7 @@ test {
bootWar {
archiveFileName = "eapim-portal-boot.war"
mainClass = 'com.eactive.apim.portal.PortalApplication'
}
war {
@@ -5,14 +5,18 @@ import com.eactive.apim.portal.apps.community.partnership.mapper.PartnershipAppl
import com.eactive.apim.portal.common.user.PortalAuthenticatedUser;
import com.eactive.apim.portal.common.util.SecurityUtil;
import com.eactive.apim.portal.common.util.UserTypeUtil;
import com.eactive.apim.portal.djb.community.qna.comment.service.CommunityAdminNotifier;
import com.eactive.apim.portal.file.entity.FileInfo;
import com.eactive.apim.portal.file.service.FileService;
import com.eactive.apim.portal.file.service.FileTypeContext;
import com.eactive.apim.portal.partnershipapplication.entity.PartnershipApplication;
import com.eactive.apim.portal.template.entity.MessageCode;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@Service
@RequiredArgsConstructor
@@ -21,6 +25,8 @@ public class PartnershipApplicationFacadeImpl implements PartnershipApplicationF
private final PartnershipApplicationService partnershipApplicationService;
private final PartnershipApplicationMapper partnershipApplicationMapper;
private final FileService fileService;
// portal-admin 알림 발행기(범용). Q&A 등록 알림과 동일 컴포넌트를 재사용한다.
private final CommunityAdminNotifier portalAdminNotifier;
@Override
@@ -43,5 +49,15 @@ public class PartnershipApplicationFacadeImpl implements PartnershipApplicationF
partnershipApplication.setFileId(file.getFileId());
}
partnershipApplicationService.createPartnershipApplication(partnershipApplication);
// 개선요청/제휴 게시물 등록 시 portal-admin 에게 알림 (INQUIRY_CREATED 와 동일 패턴)
PortalAuthenticatedUser writer = SecurityUtil.getPortalAuthenticatedUser();
Map<String, Object> params = new HashMap<>();
params.put("partnershipId", partnershipApplication.getId());
params.put("bizSubject", partnershipApplication.getBizSubject());
if (writer != null) {
params.put("writerName", writer.getUserName());
}
portalAdminNotifier.notifyPortalAdmins(MessageCode.PARTNERSHIP_CREATED, params);
}
}
@@ -6,7 +6,7 @@ import com.eactive.apim.portal.apps.community.qna.mapper.InquiryMapper;
import com.eactive.apim.portal.common.user.PortalAuthenticatedUser;
import com.eactive.apim.portal.common.util.SecurityUtil;
import com.eactive.apim.portal.common.util.StringMaskingUtil;
import com.eactive.apim.portal.djb.community.qna.comment.service.InquiryAdminNotifier;
import com.eactive.apim.portal.djb.community.qna.comment.service.CommunityAdminNotifier;
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums;
import com.eactive.apim.portal.qna.entity.Inquiry;
import com.eactive.apim.portal.template.entity.MessageCode;
@@ -26,7 +26,7 @@ public class InquiryFacadeImpl implements InquiryFacade {
private final InquiryService inquiryService;
private final InquiryMapper inquiryMapper;
private final InquiryAdminNotifier inquiryAdminNotifier;
private final CommunityAdminNotifier inquiryAdminNotifier;
@Override
public Page<InquiryDTO> getInquiries(InquirySearch search, Pageable pageable, PortalAuthenticatedUser user) {
@@ -152,25 +152,6 @@ public class AccountRecoveryController {
}
}
@PostMapping("/resend_verification_email")
public ResponseEntity<Map<String, String>> resendVerificationEmail(@RequestParam String loginId) {
Map<String, String> response = new HashMap<>();
try {
portalUserAuthService.resendVerificationEmail(loginId);
response.put("success", "인증 이메일이 재발송되었습니다.");
return ResponseEntity.ok(response);
} catch (IllegalArgumentException e) {
response.put("error", e.getMessage());
return ResponseEntity.badRequest().body(response);
} catch (Exception e) {
response.put("error", "이메일 발송 중 오류가 발생했습니다.");
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
}
}
@GetMapping("/dormant_account")
public String showDormantAccountPage(HttpSession session,Model model) {
@@ -357,24 +357,6 @@ public class UserRegisterController {
return "redirect:/";
}
@GetMapping("/validate_email")
public String validateUserEmail(@RequestParam(name = "token", required = false) String token) {
String decodedToken = new String(Base64.decode(token));
try {
String decToken = encryptionUtil.decrypt(decodedToken);
String[] tokens = decToken.split(":");
boolean approvalRequired = portalUserService.activateUser(tokens[1]);
if (approvalRequired) {
return "apps/register/emailValidationResultCorpManager";
} else {
return "apps/register/emailValidationResultUser";
}
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException |
BadPaddingException e) {
throw new IllegalArgumentException("인증 정보 오류. 관리자 문의하세요.");
}
}
// 에러 발생 시 모델 세팅을 위한 private 메서드
private void setModelForError(HttpSession session, Model model, UserAgreementDTO agreement,
@@ -122,37 +122,6 @@ public class PortalUserAuthService implements UserDetailsService {
messageHandlerService.publishEvent(UserPasswordResetEvent.KEY, recipient, params);
}
public void resendVerificationEmail(String loginId) {
PortalUser user = portalUserRepository.findByLoginId(loginId)
.orElseThrow(() -> new IllegalArgumentException("입력하신 사용자 정보가 올바르지 않습니다. 다시 확인해 주세요."));
if (user.getUserStatus().equals(PortalUserEnums.UserStatus.ACTIVE)) {
throw new IllegalArgumentException("이미 인증이 완료된 계정입니다.");
}
// Enum을 직접 전달
List<MessageRequest> messageRequests = messageRequestRepository.findByEmailAndMessageCode(
user.getLoginId(), MessageCode.USER_VERIFICATION_EMAIL
);
if (!messageRequests.isEmpty()) {
messageRequestRepository.deleteAll(messageRequests);
}
HashMap<String, Object> params = new HashMap<>();
String tokenValue = user.getCreatedDate().format(DateTimeFormatter.ofPattern("yyyyMMddHHmm")) + ":" + user.getId();
try {
String encToken = encryptionUtil.encrypt(tokenValue);
params.put("token", Base64.encode(encToken.getBytes(StandardCharsets.UTF_8)));
MessageRecipient recipient = createMessageRecipient(user);
messageHandlerService.publishEvent(MessageCode.USER_VERIFICATION_EMAIL, recipient, params);
} catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
throw new SystemException("암호화 모듈 오류");
}
}
private MessageRecipient createMessageRecipient(PortalUser user) {
MessageRecipient recipient = new MessageRecipient();
recipient.setUsername(user.getUserName());
@@ -20,7 +20,7 @@ import java.util.Map;
@Slf4j
@Service
@RequiredArgsConstructor
public class InquiryAdminNotifier {
public class CommunityAdminNotifier {
private final UserInfoRepository userInfoRepository;
private final MessageHandlerService messageHandlerService;
@@ -42,7 +42,7 @@ public class InquiryCommentFacadeImpl implements InquiryCommentFacade {
private final InquiryCommentService commentService;
private final InquiryCommentRepository commentRepository;
private final InquiryCommentPermissionChecker permissionChecker;
private final InquiryAdminNotifier adminNotifier;
private final CommunityAdminNotifier adminNotifier;
private final PortalUserRepository portalUserRepository;
private final UserInfoRepository userInfoRepository;
+6
View File
@@ -247,6 +247,9 @@ page:
corp:
name: "법인회원가입"
path: "/signup/portalOrg"
verification_email:
name: "이메일 인증"
path: "/signup/verification-email"
agreements:
name: 약관
path: "#"
@@ -322,6 +325,9 @@ page:
mypage:
name: "내 정보 관리"
path: "/mypage"
verification_email:
name: "이메일 인증"
path: "/mypage/verification-email"
user_list:
name: "이용자 관리"
path: "/users"
@@ -355,11 +355,6 @@ const customPopups = {
$('#emailValidationPopup').hide();
});
},
showEmailResendPopup: function (message, loginId) {
$('#emailResendMessage').html(customPopups._sanitizeHtml(message));
$('#userLoginId').val(loginId);
$('#emailResend').show();
},
/**
* 사용자 초대 팝업 표시
@@ -151,14 +151,7 @@
getId(form);
}
if (document.loginForm.message && document.loginForm.message.value) {
if (document.loginForm.message.value.includes("이메일 인증이 완료되지 않았습니다")) {
console.log("이메일 재발송 팝업 트리거");
let loginId = $('#loginId').val();
console.log("Retrieved loginId:", loginId);
customPopups.showEmailResendPopup(document.loginForm.message.value, loginId);
} else {
customPopups.showAlert(document.loginForm.message.value);
}
customPopups.showAlert(document.loginForm.message.value);
}
}
@@ -174,11 +167,13 @@
// 비밀번호 만료 체크 관련 코드 추가
var successMsg = [[${session.success}]];
var passwordExpired = [[${session.passwordExpired}]];
var emailVerificationRequired = [[${session.emailVerificationRequired}]];
var redirectUrl = [[${session.redirectUrl}]];
if (successMsg) {
customPopups.showAlert(successMsg, function() {
if (passwordExpired && redirectUrl) {
// 비밀번호 만료·미인증(이메일 인증 필요) 시 전용 화면으로 이동
if ((passwordExpired || emailVerificationRequired) && redirectUrl) {
window.location.href = redirectUrl;
}
});
@@ -13,7 +13,7 @@
<a href="https://www.jejubank.co.kr/hmpg/csct/secuCenr/ptctPlcy/procsPlcy/ctnt.do"
target="_blank" rel="noopener noreferrer" class="footer-link">개인정보처리방침</a>
</div>
<p class="footer-copyright">Copyright &copy; 2026 DJ Bank. All Rights Reserved.</p>
<p class="footer-copyright">Copyright &copy; 2026 JEJU Bank. All Rights Reserved.</p>
</div>
<!-- Right Section -->
@@ -3,6 +3,5 @@
<div th:replace="fragment/popup/customPopup :: #customAlert"></div>
<div th:replace="fragment/popup/emailValidationPopup :: #emailValidationPopup"></div>
<div th:replace="fragment/popup/customPopup2 :: #customConfirm"></div>
<div th:replace="fragment/popup/emailResendPopup :: emailResendPopup"></div>
<div th:replace="fragment/popup/passwordInputPopup :: passwordInputPopup"></div>
</div>
@@ -1,63 +0,0 @@
<section class="content pop" th:fragment="emailResendPopup">
<div class="popup_total" id="emailResend" style="display:none; z-index:1001;">
<form id="emailResendForm">
<input type="hidden" id="userLoginId" name="loginId" value="">
<input type="hidden" name="_csrf" id="csrfToken" th:value="${_csrf.token}"/>
<div class="pop_dim">
<div class="popup-content">
<div class="inner_txt">
<div class="title">
<h2 id="customAlertTitle2">알림</h2>
</div>
</div>
<p class="pop_text" id="emailResendMessage"></p>
<div class="pop_btnbox">
<button type="button" class="popup_button_gray" id="emailResendButton">
이메일 재발송
</button>
<button type="button" class="popup_button_blue" id="confirmButton">확인</button>
</div>
<a class="btn_close" style="margin-top:0" id="emailResendPopupCloseButton">
<img th:src="@{/img/icon/icon_close.png}" alt="닫기">
</a>
</div>
</div>
</form>
</div>
<script type="text/javascript">
// 이메일 재발송 버튼 클릭 이벤트
document.getElementById('emailResendButton').addEventListener('click', function (e) {
e.preventDefault();
const loginId = document.getElementById('userLoginId').value;
const csrfToken = document.getElementById('csrfToken').value;
// 팝업 닫기
$('#emailResend').hide();
// Ajax 요청
$.ajax({
url: '/resend_verification_email',
type: 'POST',
data: {
loginId: loginId,
_csrf: csrfToken
},
success: function (response) {
var message = response.success || response.error || '이메일 발송에 실패했습니다.';
customPopups.showAlert(message);
},
error: function (xhr, status, error) {
console.error('요청 실패:', error);
customPopups.showAlert('이메일 발송 중 오류가 발생했습니다.');
}
});
});
// 확인 버튼과 닫기 버튼 이벤트
$('#confirmButton, #emailResendPopupCloseButton').on('click', function () {
$('#emailResend').hide();
});
</script>
</section>