- API 선택 검증 로직 수정 - 선택 사항으로 변경

- '인증 키 관리' → '앱 관리' 용어 변경
- API 미선택 시 확인 팝업 로직 추가
This commit is contained in:
Rinjae
2026-07-27 18:20:37 +09:00
parent 41be827b81
commit 61be6bf108
8 changed files with 38 additions and 21 deletions
@@ -645,14 +645,8 @@ public class MyAppController {
return new ModelAndView("redirect:/myapikey/register/step1");
}
// API 선택 검증
if (selectedApis == null || selectedApis.isEmpty()) {
redirectAttributes.addFlashAttribute("error", "최소 1개 이상의 API를 선택해주세요.");
return new ModelAndView("redirect:/myapikey/register/step2");
}
// 선택된 API를 세션에 저장
registration.setSelectedApis(selectedApis);
// API 선택은 선택 사항 — 미선택(빈 목록)도 허용한다.
registration.setSelectedApis(selectedApis != null ? selectedApis : new ArrayList<>());
// 등록이 완료되었는지 최종 검증
if (!registration.isComplete()) {
@@ -99,6 +99,7 @@ public class ApiKeyRegistrationDTO implements Serializable {
}
public boolean isComplete() {
return isStep1Complete() && isStep2Complete();
// API 선택은 선택 사항이므로 기본 정보(Step1)만 완료되면 등록 가능하다.
return isStep1Complete();
}
}
@@ -9,7 +9,6 @@ import com.eactive.apim.portal.apps.user.dto.PortalOrgDTO;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import javax.validation.constraints.NotEmpty;
import lombok.Data;
@Data
@@ -25,8 +24,7 @@ public class AppRequestDTO {
private ApprovalDTO approval;
@NotEmpty
private String apiList = ""; //comma separated api id list
private String apiList = ""; //comma separated api id list (미선택 허용)
private String apiGroupList = ""; //comma separated api group id list
+1 -1
View File
@@ -361,7 +361,7 @@ page:
name: "이용자 정보"
path: "/users/detail"
apikey:
name: "인증키 관리"
name: " 관리"
path: "/myapikey"
app_request_detail:
name: "인증키 신청 상세"
+28 -4
View File
@@ -447,18 +447,42 @@ document.addEventListener('DOMContentLoaded', function() {
});
}
// Form validation
// Form submit
// - Webhook/앱 변경은 API 가 필수(form data-api-required=true)이므로 미선택 시 차단한다.
// - 앱 신청(myapikey register)은 선택 사항이라, 미선택 시 확인 팝업으로 한 번 더 묻고 진행한다.
form.addEventListener('submit', function(e) {
if (selectedApis.size === 0) {
if (selectedApis.size !== 0) {
syncHiddenSelected();
return;
}
var apiRequired = form.dataset.apiRequired === 'true';
if (apiRequired) {
e.preventDefault();
if (window.customPopups && customPopups.showAlert) {
if (typeof customPopups !== 'undefined' && customPopups.showAlert) {
customPopups.showAlert('최소 1개 이상의 API를 선택해주세요.');
} else {
alert('최소 1개 이상의 API를 선택해주세요.');
}
return false;
}
syncHiddenSelected();
// 미선택 상태로 앱 신청 → 확인 후 진행
e.preventDefault();
var message = '선택한 API가 없습니다. API 없이 앱을 신청하시겠습니까?';
// custom-popups.js 는 top-level const 라 window.customPopups 가 아닌 렉시컬 전역이다.
if (typeof customPopups !== 'undefined' && customPopups.showConfirm) {
customPopups.showConfirm(message, function (ok) {
if (ok) {
syncHiddenSelected();
form.submit(); // submit() 은 submit 이벤트를 재발생시키지 않음 → 재확인 루프 없음
}
});
} else if (window.confirm(message)) {
syncHiddenSelected();
form.submit();
}
return false;
});
// Initialize
@@ -56,7 +56,7 @@
<div class="s2-selection-container">
<main class="s2-content-area">
<form id="apiSelectorForm" method="post" th:action="@{${formAction}}" class="s2-form"
th:attr="data-save-action=@{${saveAction}}">
th:attr="data-save-action=@{${saveAction}}, data-api-required=${!#strings.contains(formAction, '/myapikey/register')}">
<!-- Header filter: Search and Select All -->
<div class="s2-filter-header">
@@ -92,7 +92,7 @@
<a th:href="@{/users}"><i class="fas fa-users"></i>이용자 관리</a>
</li>
<li sec:authorize="hasRole('ROLE_APP')">
<a th:href="@{/myapikey}"><i class="fas fa-key"></i>인증 키 관리</a>
<a th:href="@{/myapikey}"><i class="fas fa-key"></i> 관리</a>
<a th:href="@{/webhook}" sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"><i class="fas fa-bell"></i>Webhook 관리</a>
<a th:href="@{/statistics/api}"><i class="fas fa-chart-bar"></i>이용 통계</a>
</li>
@@ -249,7 +249,7 @@
</button>
<ul class="drawer-submenu">
<li sec:authorize="hasRole('ROLE_USER_MANAGER')"><a th:href="@{/users}">이용자 관리</a></li>
<li sec:authorize="hasRole('ROLE_APP')"><a th:href="@{/myapikey}">인증 키 관리</a></li>
<li sec:authorize="hasRole('ROLE_APP')"><a th:href="@{/myapikey}"> 관리</a></li>
<li sec:authorize="hasRole('ROLE_API_KEY_REQUEST')"><a th:href="@{/webhook}">Webhook 관리</a></li>
<li sec:authorize="hasRole('ROLE_APP')"><a th:href="@{/statistics/api}">이용 통계</a></li>
<li><a th:href="@{/mypage}">내 정보 관리</a></li>
@@ -57,7 +57,7 @@
<a th:href="@{/myapikey}"
th:classappend="${activeMenu == 'apiKey'} ? 'service-nav__item--active' : ''"
class="service-nav__item">인증 키 관리</a>
class="service-nav__item"> 관리</a>
<a th:href="@{/webhook}"
th:classappend="${activeMenu == 'webhook'} ? 'service-nav__item--active' : ''"