GW 클라이언트 해지 처리 로직 추가 - BLOCK/DELETE 처리방식 지원

- APP 승인 시 GW 처리방식 설정 기능 추가 및 상세 표시
- DELETE 요청 처리 중 클라이언트 상태 동기화 로직 개선
- JSP에 GW 처리방식 선택 UI 및 승인 결과 표시 추가
This commit is contained in:
Rinjae
2026-07-30 16:23:09 +09:00
parent 90ba584e4b
commit 8abe0a8585
5 changed files with 98 additions and 11 deletions
@@ -66,8 +66,8 @@ public class PortalApprovalManController extends BaseAnnotationController {
}
@PostMapping(value = "/onl/apim/approval/portalApprovalMan.json", params = "cmd=APPROVE")
public ResponseEntity<Void> approve(String id) {
portalApprovalManService.approve(id, SessionManager.getLoginVo().getUserId());
public ResponseEntity<Void> approve(String id, @RequestParam(required = false) String gwAction) {
portalApprovalManService.approve(id, SessionManager.getLoginVo().getUserId(), gwAction);
return ResponseEntity.ok().build();
}
@@ -2,6 +2,8 @@ package com.eactive.eai.rms.onl.apim.approval;
import com.eactive.apim.portal.apispec.service.ApiSpecInfoService;
import com.eactive.apim.portal.apprequest.entity.AppRequest;
import com.eactive.apim.portal.apprequest.entity.AppRequestType;
import com.eactive.apim.portal.apprequest.entity.GwAction;
import com.eactive.apim.portal.apprequest.repository.AppRequestRepository;
import com.eactive.apim.portal.approval.entity.Approval;
import com.eactive.apim.portal.approval.entity.ApprovalType;
@@ -56,6 +58,7 @@ public class PortalApprovalManService extends BaseService {
private static final String HARD_DELETE_FLAG_KEY = "approval.hard-delete.enabled";
private final ApprovalService approvalService;
private final PortalApprovalUIMapper portalApprovalUIMapper;
private final ApprovalStateMachine approvalStateMachine;
private final AppRequestRepository appRequestRepository;
private final PortalAppApprovalListener portalAppApprovalListener;
@@ -77,12 +80,18 @@ public class PortalApprovalManService extends BaseService {
private EntityManager entityManager;
public Page<PortalApprovalUI> selectList(Pageable pageable, PortalApprovalUISearch portalApprovalUISearch) {
// 목록 그리드는 Approval 자체 필드(제목/유형/상태/요청자/생성일/예상완료일)만 사용하므로
// 행별 상세 재조회(getDetailWithMaskOption: AppRequest + API 목록 + AGW 크로스 조회) 없이 경량 매핑한다.
Page<Approval> approval = approvalService.findAll(pageable, portalApprovalUISearch);
return approval.map(entity -> {
try {
return getDetailWithMaskOption(entity.getId(), false);
PortalApprovalUI ui = portalApprovalUIMapper.toVo(entity);
if (ui.getRequester() == null) {
ui.setRequester(createDeletedUserPlaceholder());
}
return ui;
} catch (Exception e) {
logger.error("승인 상세 조회 실패 - ID: {}, 오류: {}", entity.getId(), e.getMessage());
logger.error("승인 목록 매핑 실패 - ID: {}, 오류: {}", entity.getId(), e.getMessage());
return null;
}
});
@@ -204,6 +213,7 @@ public class PortalApprovalManService extends BaseService {
if (optRequest.isPresent()) {
AppRequest appRequest = optRequest.get();
appApprovalUI.setRequestType(appRequest.getType());
appApprovalUI.setGwAction(appRequest.getGwAction());
if (appRequest.getApiGroupList() == null || appRequest.getApiGroupList().isEmpty()) {
@@ -321,7 +331,7 @@ public class PortalApprovalManService extends BaseService {
return placeholder;
}
public void approve(String id, String approverId) {
public void approve(String id, String approverId, String gwAction) {
Map options = new HashMap<>();
Approval approval = approvalService.findById(id).orElseThrow(() -> new IllegalArgumentException("승인 정보를 찾을 수 없습니다. ID: " + id));
@@ -329,6 +339,18 @@ public class PortalApprovalManService extends BaseService {
throw new IllegalArgumentException("아직 승인 차례가 아닙니다.");
}
// API 이용해지(DELETE) 승인이면 GW 처리방식(차단/완전삭제)을 신청서에 영속화한다.
// 같은 EMS 트랜잭션이므로 최종 승인 시 listener 가 이 값을 읽고, REDEPLOY 재처리에서도 유지된다.
// 미지정(null)은 안전 기본값인 차단(BLOCK)으로 처리.
if (approval.getApprovalType().equals(ApprovalType.APP)) {
appRequestRepository.findById(approval.getTargetId()).ifPresent(request -> {
if (AppRequestType.DELETE.equals(request.getType())) {
request.setGwAction("DELETE".equalsIgnoreCase(gwAction) ? GwAction.DELETE : GwAction.BLOCK);
appRequestRepository.save(request);
}
});
}
options.put(ApprovalConstants.APPROVER, approverId);
sendEvent(id, ApprovalEvent.APPROVE, options);
}
@@ -2,6 +2,7 @@ package com.eactive.eai.rms.onl.apim.approval.app;
import com.eactive.apim.portal.apprequest.entity.AppRequest;
import com.eactive.apim.portal.apprequest.entity.AppRequestType;
import com.eactive.apim.portal.apprequest.entity.GwAction;
import com.eactive.apim.portal.apprequest.repository.AppRequestRepository;
import com.eactive.apim.portal.approval.entity.Approval;
import com.eactive.apim.portal.approval.service.ApprovalDeployException;
@@ -72,7 +73,7 @@ public class PortalAppApprovalListener implements ApprovalListener {
// 위 메서드가 반환되면 트랜잭션이 커밋되어 Portal DB에 영구 저장됨
// 이제 APIGW 동기화 및 GW 리로드 수행
syncTargetServer(type, credentialUI);
syncTargetServer(appRequest, credentialUI);
sendApprovalResult(appRequest);
}
}
@@ -94,7 +95,12 @@ public class PortalAppApprovalListener implements ApprovalListener {
} else if (type.equals(AppRequestType.MODIFY)) {
credentialUI = modifyClientUI(appRequest);
} else if (type.equals(AppRequestType.DELETE)) {
credentialManService.delete(appRequest.getClientId());
// REDEPLOY 재처리 시 credential 이 이미 삭제되어 있을 수 있으므로 부재는 정상 통과시킨다.
try {
credentialManService.delete(appRequest.getClientId());
} catch (org.springframework.dao.EmptyResultDataAccessException e) {
logger.warn("포털 credential 이미 삭제됨 (재처리 통과) - clientId: {}", appRequest.getClientId());
}
credentialUI = new CredentialUI();
credentialUI.setClientid(appRequest.getClientId());
}
@@ -119,7 +125,9 @@ public class PortalAppApprovalListener implements ApprovalListener {
messageSendService.sendMessage(MessageCode.APP_APPROVE, recipient, params);
}
private void syncTargetServer(AppRequestType action, CredentialUI credentialUI) throws ApprovalDeployException {
private void syncTargetServer(AppRequest appRequest, CredentialUI credentialUI) throws ApprovalDeployException {
AppRequestType action = appRequest.getType();
DataSourceType type = DataSourceTypeManager.getDataSourceType("APIGW");
DataSourceContextHolder.setDataSourceType(type);
@@ -129,7 +137,7 @@ public class PortalAppApprovalListener implements ApprovalListener {
} else if (action.equals(AppRequestType.MODIFY)) {
clientManService.update(credentialUIMapper.mapClient(credentialUI));
} else if (action.equals(AppRequestType.DELETE)) {
clientManService.delete(credentialUI.getClientid());
applyGwActionForDelete(appRequest.getGwAction(), credentialUI.getClientid());
}
CommonCommand.builder()
@@ -138,6 +146,30 @@ public class PortalAppApprovalListener implements ApprovalListener {
.build().broadcast(agentUtilService);
}
/**
* API 이용해지 승인 시 GW 클라이언트(TSEAIAU01) 처리.
* 승인 시점에 관리자가 선택해 PTL_APP_REQUEST.GW_ACTION 에 영속화된 값을 따른다.
* - DELETE: 행 완전 삭제 / - BLOCK 또는 null(미지정): 차단(appstatus='0')
* GW 에 행이 이미 없으면(선삭제·재처리) 목적이 달성된 상태이므로 통과시키고,
* 그 외 오류는 ApprovalDeployException 으로 던져 FAILED(재처리 가능) 상태를 만든다.
*/
private void applyGwActionForDelete(GwAction gwAction, String clientId) throws ApprovalDeployException {
try {
if (GwAction.DELETE.equals(gwAction)) {
clientManService.delete(clientId);
logger.info("GW 클라이언트 완전 삭제 - clientId: {}", clientId);
} else {
clientManService.blockClient(clientId);
logger.info("GW 클라이언트 차단(appstatus=0) - clientId: {}", clientId);
}
} catch (org.springframework.dao.EmptyResultDataAccessException | javax.persistence.EntityNotFoundException e) {
logger.warn("GW 클라이언트가 이미 존재하지 않아 처리 생략 (재처리 통과) - clientId: {}", clientId);
} catch (RuntimeException e) {
logger.error("GW 클라이언트 해지 처리 실패 - clientId: {}, gwAction: {}", clientId, gwAction, e);
throw new ApprovalDeployException("GW 클라이언트 해지 처리에 실패했습니다: " + e.getMessage());
}
}
private CredentialUI modifyClientUI(AppRequest appRequest) {
CredentialUI existingCredential = credentialManService.selectDetail(appRequest.getClientId());
existingCredential.getApiList().clear();
@@ -1,6 +1,7 @@
package com.eactive.eai.rms.onl.apim.approval.app;
import com.eactive.apim.portal.apprequest.entity.AppRequestType;
import com.eactive.apim.portal.apprequest.entity.GwAction;
import com.eactive.eai.rms.onl.apim.apigroup.ui.ApiGroupUI;
import com.eactive.eai.rms.onl.apim.approval.PortalApprovalUI;
import java.util.ArrayList;
@@ -26,4 +27,7 @@ public class PortalAppApprovalUI extends PortalApprovalUI {
private List<String> prevApiGroupNameList = new ArrayList<>();
private AppRequestType requestType;
//DELETE 승인 시 선택된 GW 처리방식 (승인 완료 건 상세 표시용)
private GwAction gwAction;
}