강제 반려 기능 추가

- 삭제된 승인자 있는 승인 요청 강제 반려 로직 추가
- JSP/JS: 강제 반려 버튼 추가 및 승인 상태별 표시 로직 구현
This commit is contained in:
Rinjae
2026-07-24 17:22:10 +09:00
parent c224f80cdf
commit e7297458f6
5 changed files with 137 additions and 7 deletions
@@ -41,7 +41,7 @@ public class DjbProperty {
description = "API 접근 허용 IP 목록 (콤마(,)로 구분된 IP들, 예: 192.168.0.1, 192.168.1.*,127.*.*.*",
defaultValue = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*"
)
private String apiAllowIpList = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*";
private String dapiAllowIpList = "10.15.106.*, 10.14.8.*, 10.15.8.*, 192.168.240.*, 127.0.0.1, 192.168.132.*, 192.168.131.*";
@@ -77,6 +77,15 @@ public class PortalApprovalManController extends BaseAnnotationController {
return ResponseEntity.ok().build();
}
@PostMapping(value = "/onl/apim/approval/portalApprovalMan.json", params = "cmd=FORCE_REJECT")
public ResponseEntity<Void> forceReject(String id, String rejectReason) {
if (StringUtils.isBlank(rejectReason)) {
throw new BizException("강제 반려 사유를 입력해 주세요.");
}
portalApprovalManService.forceReject(id, SessionManager.getLoginVo().getUserId(), rejectReason);
return ResponseEntity.ok().build();
}
@PostMapping(value = "/onl/apim/approval/portalApprovalMan.json", params = "cmd=REDEPLOY")
public ResponseEntity<Void> redeploy(String id) {
portalApprovalManService.redeploy(id);
@@ -5,6 +5,7 @@ import com.eactive.apim.portal.apprequest.entity.AppRequest;
import com.eactive.apim.portal.apprequest.repository.AppRequestRepository;
import com.eactive.apim.portal.approval.entity.Approval;
import com.eactive.apim.portal.approval.entity.ApprovalType;
import com.eactive.apim.portal.approval.entity.ApproverStatus;
import com.eactive.apim.portal.approval.statemachine.*;
import com.eactive.apim.portal.portalproperty.service.PortalPropertyService;
import com.eactive.apim.portal.portaluser.entity.PortalUser;
@@ -41,6 +42,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.time.LocalDateTime;
import java.util.*;
@Service
@@ -342,6 +344,51 @@ public class PortalApprovalManService extends BaseService {
sendEvent(id, ApprovalEvent.DENY, options);
}
/**
* 강제 반려: 승인자 목록에 삭제된 사용자가 있어 승인 진행이 불가능한 건을
* 승인자가 아닌 관리자도 반려 처리할 수 있다. (요청됨/진행중 상태에서만 허용)
*/
public void forceReject(String id, String adminUserId, String rejectReason) {
Approval approval = approvalService.findById(id)
.orElseThrow(() -> new IllegalArgumentException("승인 정보를 찾을 수 없습니다. ID: " + id));
ApprovalState currentStatus = approval.getApprovalStatus();
if (!(currentStatus instanceof RequestedState) && !(currentStatus instanceof ProcessingState)) {
throw new BizException("요청됨/진행중 상태의 승인 요청만 강제 반려할 수 있습니다.");
}
boolean hasDeletedApprover = approval.getApprovers().stream()
.anyMatch(approver -> approver.getUser() == null);
if (!hasDeletedApprover) {
throw new BizException("승인자 목록에 삭제된 사용자가 있는 경우에만 강제 반려할 수 있습니다.");
}
approval.getApprovers().forEach(approver -> {
if (approver.getUser() == null
&& (ApproverStatus.CURRENT.equals(approver.getApproverStatus())
|| ApproverStatus.PENDING.equals(approver.getApproverStatus()))) {
approver.setApproverStatus(ApproverStatus.DENIED);
approver.setApprovedDate(LocalDateTime.now());
approver.setApprovalMessage("[관리자 강제 반려: " + adminUserId + "] " + rejectReason);
}
});
approval.setApprovalStatus(new DeniedState());
Map<String, Object> options = new HashMap<>();
options.put(ApprovalConstants.APPROVER, adminUserId);
options.put((String) ApprovalConstants.MESSAGE, rejectReason);
options.put("authorizer", portalApprovalAuthorizer);
if (approval.getApprovalType().equals(ApprovalType.APP)) {
options.put("listener", portalAppApprovalListener);
} else if (approval.getApprovalType().equals(ApprovalType.USER)) {
options.put("listener", portalUserApprovalListener);
}
// DENY 이벤트는 authorizer 검증에 걸리므로 상태를 직접 DENIED 로 만든 뒤 END 로 롤백만 수행
approvalStateMachine.transition(approval, ApprovalEvent.END, options);
approvalService.save(approval);
logger.info("Approval {} force-rejected by admin {} (deleted approver present)", id, adminUserId);
}
public void update(String id, String expectEndDate) {
Approval approval = approvalService.findById(id)
.orElseThrow(() -> new IllegalArgumentException("승인 정보를 찾을 수 없습니다. ID: " + id));