인증정보 -> 개발자포탈 정보 반영
This commit is contained in:
@@ -285,6 +285,56 @@
|
||||
}
|
||||
});
|
||||
|
||||
$("#btn_sync_portal").click(function() {
|
||||
var clientId = $('input[name=clientId]').val();
|
||||
var clientName = $('input[name=clientName]').val();
|
||||
|
||||
if (!clientId) {
|
||||
alert("Client ID가 없습니다.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirm("'" + clientName + "'의 개발자포탈 정보를 반영하시겠습니까?\n\n" +
|
||||
"APIGW 인증 정보를 포탈 DB에 반영합니다. (없으면 생성, 있으면 업데이트)")) {
|
||||
return;
|
||||
}
|
||||
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: url,
|
||||
dataType: "json",
|
||||
data: {
|
||||
cmd: 'SYNC_PORTAL',
|
||||
clientId: clientId
|
||||
},
|
||||
success: function(response) {
|
||||
if (response.success) {
|
||||
var msg = "포탈 정보 반영 완료";
|
||||
|
||||
if (response.action === 'INSERTED') {
|
||||
msg = "포탈 정보를 새로 생성했습니다.";
|
||||
} else if (response.action === 'UPDATED') {
|
||||
msg = "포탈 정보를 업데이트했습니다.";
|
||||
} else if (response.action === 'SKIPPED_NO_ORG') {
|
||||
msg = "반영을 건너뜁니다.\n법인(orgId)이 설정되지 않은 클라이언트입니다.";
|
||||
} else if (response.action === 'SKIPPED_INVALID_API') {
|
||||
msg = "반영을 건너뜁니다.\n존재하지 않는 API가 포함되어 있습니다.\n\n";
|
||||
if (response.invalidApis && response.invalidApis.length > 0) {
|
||||
msg += "누락된 API: " + response.invalidApis.join(", ");
|
||||
}
|
||||
}
|
||||
|
||||
alert(msg);
|
||||
} else {
|
||||
alert("반영 실패\n\n" + response.message);
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
alert("반영 중 오류가 발생했습니다.");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$("#btn_popup_api").click(function () {
|
||||
const args = {};
|
||||
const url2 = api_url_view += "?cmd=POPUP";
|
||||
@@ -417,6 +467,8 @@
|
||||
</div><!-- end content_top -->
|
||||
<div class="content_middle">
|
||||
<div class="search_wrap">
|
||||
<button type="button" class="cssbtn" id="btn_sync_portal" level="W" status="DETAIL"><i class="material-icons">sync</i> 개발자포탈 정보 반영
|
||||
</button>
|
||||
<button type="button" class="cssbtn" id="btn_delete" level="W" status="DETAIL"><i class="material-icons">delete</i> <%= localeMessage.getString("button.delete") %>
|
||||
</button>
|
||||
<button type="button" class="cssbtn" id="btn_modify" level="W" status="DETAIL,NEW"><i
|
||||
|
||||
@@ -55,4 +55,6 @@ public class CredentialUI implements Serializable, com.eactive.eai.data.Data {
|
||||
private List<ApiSpecInfoUI> apiList = new ArrayList<>();
|
||||
|
||||
private String appIconFileId;
|
||||
|
||||
private String appDescription;
|
||||
}
|
||||
|
||||
@@ -121,4 +121,37 @@ public class ClientController extends OnlBaseAnnotationController {
|
||||
response.put("hasMtls", hasMtls);
|
||||
return ResponseEntity.ok(response);
|
||||
}
|
||||
|
||||
/**
|
||||
* APIGW 인증관리 정보를 개발자포탈에 반영합니다.
|
||||
* 포탈에 없으면 신규 생성, 있으면 업데이트합니다.
|
||||
*
|
||||
* @param clientId 클라이언트 ID
|
||||
* @return 반영 결과 (success, action, message, invalidApis)
|
||||
*/
|
||||
@PostMapping(value = "/onl/admin/authserver/clientMan.json", params = "cmd=SYNC_PORTAL")
|
||||
public ResponseEntity<Map<String, Object>> syncPortalData(String clientId) {
|
||||
try {
|
||||
SyncResult result = clientManService.syncPortalData(clientId);
|
||||
|
||||
Map<String, Object> response = new HashMap<>();
|
||||
response.put("success", result.isSuccess());
|
||||
response.put("message", result.getMessage());
|
||||
response.put("action", result.getAction().name());
|
||||
|
||||
// 유효하지 않은 API 목록 포함
|
||||
if (result.getInvalidApis() != null && !result.getInvalidApis().isEmpty()) {
|
||||
response.put("invalidApis", result.getInvalidApis());
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(response);
|
||||
} catch (Exception e) {
|
||||
// 에러 처리
|
||||
Map<String, Object> error = new HashMap<>();
|
||||
error.put("success", false);
|
||||
error.put("message", "반영 중 오류: " + e.getMessage());
|
||||
error.put("action", "ERROR");
|
||||
return ResponseEntity.status(500).body(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+180
-1
@@ -1,9 +1,20 @@
|
||||
package com.eactive.eai.rms.onl.manage.authserver.client;
|
||||
|
||||
import com.eactive.apim.portal.app.entity.Credential;
|
||||
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||
import com.eactive.eai.data.entity.onl.eaimsg.EAIMessageEntity;
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceContextHolder;
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceType;
|
||||
import com.eactive.eai.rms.common.datasource.DataSourceTypeManager;
|
||||
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgService;
|
||||
import com.eactive.eai.rms.data.entity.onl.eaimsg.EAIMessageRepository;
|
||||
import com.eactive.eai.rms.onl.apim.approval.credential.CredentialManService;
|
||||
import com.eactive.eai.rms.onl.apim.approval.credential.CredentialService;
|
||||
import com.eactive.eai.rms.onl.apim.approval.credential.CredentialUI;
|
||||
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgUI;
|
||||
import com.eactive.eai.rms.onl.apim.portalorg.PortalOrgUIMapper;
|
||||
import com.eactive.eai.rms.onl.transaction.apim.ui.ApiSpecInfoUI;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
@@ -15,8 +26,10 @@ import com.eactive.eai.rms.common.base.OnlBaseService;
|
||||
import com.eactive.eai.rms.data.entity.onl.authserver.ClientEntityService;
|
||||
import com.eactive.eai.rms.data.entity.onl.authserver.ClientSearch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@@ -27,16 +40,25 @@ public class ClientManService extends OnlBaseService {
|
||||
private ClientUIMapper clientUIMapper;
|
||||
private PortalOrgService portalOrgService;
|
||||
private PortalOrgUIMapper portalOrgUIMapper;
|
||||
private CredentialManService credentialManService;
|
||||
private CredentialService credentialService;
|
||||
private EAIMessageRepository eaiMessageRepository;
|
||||
|
||||
@Autowired
|
||||
public ClientManService(ClientEntityService clientEntityService,
|
||||
ClientUIMapper clientUIMapper,
|
||||
PortalOrgService portalOrgService,
|
||||
PortalOrgUIMapper portalOrgUIMapper) {
|
||||
PortalOrgUIMapper portalOrgUIMapper,
|
||||
CredentialManService credentialManService,
|
||||
CredentialService credentialService,
|
||||
EAIMessageRepository eaiMessageRepository) {
|
||||
this.clientEntityService = clientEntityService;
|
||||
this.clientUIMapper = clientUIMapper;
|
||||
this.portalOrgService = portalOrgService;
|
||||
this.portalOrgUIMapper = portalOrgUIMapper;
|
||||
this.credentialManService = credentialManService;
|
||||
this.credentialService = credentialService;
|
||||
this.eaiMessageRepository = eaiMessageRepository;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,4 +105,161 @@ public class ClientManService extends OnlBaseService {
|
||||
.map(ClientEntity::getClientid)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* AGW 인증관리(ClientEntity)의 정보를 개발자포탈(Credential)에 반영합니다.
|
||||
* 포탈에 없으면 신규 생성(INSERT), 있으면 업데이트(UPDATE)합니다.
|
||||
*
|
||||
* @param clientId 클라이언트 ID
|
||||
* @return 반영 결과 (INSERTED, UPDATED, SKIPPED_NO_ORG, SKIPPED_INVALID_API, ERROR)
|
||||
*/
|
||||
public SyncResult syncPortalData(String clientId) {
|
||||
try {
|
||||
// 1. APIGW 스키마에서 ClientEntity 조회
|
||||
ClientEntity clientEntity = clientEntityService.getById(clientId);
|
||||
|
||||
// 2. 유효성 검증 - orgId 확인
|
||||
String orgId = clientEntity.getOrgid();
|
||||
if (StringUtils.isBlank(orgId)) {
|
||||
return SyncResult.builder()
|
||||
.success(false)
|
||||
.action(SyncResult.SyncAction.SKIPPED_NO_ORG)
|
||||
.message("법인(orgId)이 설정되지 않은 클라이언트입니다.")
|
||||
.build();
|
||||
}
|
||||
|
||||
// 3. API 유효성 검증 (APIGW 스키마)
|
||||
List<String> invalidApis = new ArrayList<>();
|
||||
if (clientEntity.getApiList() != null) {
|
||||
for (EAIMessageEntity apiEntity : clientEntity.getApiList()) {
|
||||
String eaiSvcName = apiEntity.getEaiSvcName();
|
||||
// APIGW에 실제 API 존재하는지 확인
|
||||
if (!eaiMessageRepository.existsById(eaiSvcName)) {
|
||||
invalidApis.add(eaiSvcName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 유효하지 않은 API가 있으면 반영 중단
|
||||
if (!invalidApis.isEmpty()) {
|
||||
return SyncResult.builder()
|
||||
.success(false)
|
||||
.action(SyncResult.SyncAction.SKIPPED_INVALID_API)
|
||||
.invalidApis(invalidApis)
|
||||
.message("존재하지 않는 API: " + String.join(", ", invalidApis))
|
||||
.build();
|
||||
}
|
||||
|
||||
// 4. MONITORING 스키마로 전환
|
||||
DataSourceType monitoringType = DataSourceTypeManager.getDataSourceType("MONITORING");
|
||||
DataSourceContextHolder.setDataSourceType(monitoringType);
|
||||
|
||||
// 5. 기존 Credential 확인
|
||||
Optional<Credential> existingCredential = credentialService.getRepository()
|
||||
.findOne((root, query, cb) -> cb.and(
|
||||
cb.equal(root.get("clientid"), clientId),
|
||||
cb.equal(root.get("orgid"), orgId)
|
||||
));
|
||||
|
||||
// 6. 데이터 변환 (ClientEntity → CredentialUI)
|
||||
CredentialUI credentialUI = convertToCredentialUI(clientEntity);
|
||||
|
||||
SyncResult.SyncAction action;
|
||||
if (existingCredential.isPresent()) {
|
||||
// 업데이트: 기존 값 유지해야 할 필드 처리
|
||||
Credential existing = existingCredential.get();
|
||||
if (StringUtils.isNotBlank(existing.getAppDescription())) {
|
||||
credentialUI.setAppDescription(existing.getAppDescription());
|
||||
}
|
||||
if (StringUtils.isNotBlank(existing.getAppIconFileId())) {
|
||||
credentialUI.setAppIconFileId(existing.getAppIconFileId());
|
||||
}
|
||||
if (StringUtils.isNotBlank(existing.getServer())) {
|
||||
credentialUI.setServer(existing.getServer());
|
||||
}
|
||||
|
||||
// 7. 포탈 스키마에 업데이트
|
||||
credentialManService.update(credentialUI);
|
||||
action = SyncResult.SyncAction.UPDATED;
|
||||
} else {
|
||||
// 신규 생성: 기본값 설정
|
||||
if (StringUtils.isBlank(credentialUI.getAppDescription())) {
|
||||
credentialUI.setAppDescription("APIGW에서 반영된 인증정보");
|
||||
}
|
||||
|
||||
// 7. 포탈 스키마에 신규 생성
|
||||
credentialManService.insert(credentialUI);
|
||||
action = SyncResult.SyncAction.INSERTED;
|
||||
}
|
||||
|
||||
return SyncResult.builder()
|
||||
.success(true)
|
||||
.action(action)
|
||||
.message("포탈 정보 반영 완료")
|
||||
.build();
|
||||
|
||||
} catch (Exception e) {
|
||||
logger.error("포탈 정보 반영 중 오류 발생", e);
|
||||
return SyncResult.builder()
|
||||
.success(false)
|
||||
.action(SyncResult.SyncAction.ERROR)
|
||||
.message("반영 중 오류: " + e.getMessage())
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ClientEntity를 CredentialUI로 변환합니다.
|
||||
*
|
||||
* @param clientEntity APIGW 클라이언트 엔티티
|
||||
* @return CredentialUI 포탈 인증정보 UI 객체
|
||||
*/
|
||||
private CredentialUI convertToCredentialUI(ClientEntity clientEntity) {
|
||||
CredentialUI credentialUI = new CredentialUI();
|
||||
|
||||
// 기본 인증정보
|
||||
credentialUI.setClientid(clientEntity.getClientid());
|
||||
credentialUI.setClientname(clientEntity.getClientname());
|
||||
credentialUI.setClientsecret(clientEntity.getClientsecret());
|
||||
|
||||
// OAuth 설정
|
||||
credentialUI.setScope(clientEntity.getScope());
|
||||
credentialUI.setGranttypes(clientEntity.getGranttypes());
|
||||
credentialUI.setAccesstokenvalidityseconds(clientEntity.getAccesstokenvalidityseconds());
|
||||
credentialUI.setRefreshtokenvalidityseconds(clientEntity.getRefreshtokenvalidityseconds());
|
||||
|
||||
// 보안 설정
|
||||
credentialUI.setAllowedips(clientEntity.getAllowedips());
|
||||
credentialUI.setAuthorities(clientEntity.getAuthorities());
|
||||
credentialUI.setRedirecturi(clientEntity.getRedirecturi());
|
||||
credentialUI.setSecuritykey(clientEntity.getSecuritykey());
|
||||
credentialUI.setAutoapprove(clientEntity.getAutoapprove());
|
||||
credentialUI.setResourceids(clientEntity.getResourceids());
|
||||
|
||||
// 조직 정보
|
||||
credentialUI.setOrgid(clientEntity.getOrgid());
|
||||
credentialUI.setOrgname(clientEntity.getOrgname());
|
||||
|
||||
// 앱 상태
|
||||
credentialUI.setAppstatus(clientEntity.getAppstatus());
|
||||
credentialUI.setDailytokenlimit(Integer.parseInt(
|
||||
StringUtils.defaultIfBlank(clientEntity.getDailytokenlimit(), "0")));
|
||||
|
||||
// 수정 정보
|
||||
credentialUI.setModifiedby(clientEntity.getModifiedby());
|
||||
credentialUI.setModifiedon(clientEntity.getModifiedon());
|
||||
|
||||
// API 목록 변환
|
||||
List<ApiSpecInfoUI> apiList = new ArrayList<>();
|
||||
if (clientEntity.getApiList() != null) {
|
||||
for (EAIMessageEntity apiEntity : clientEntity.getApiList()) {
|
||||
ApiSpecInfoUI apiUI = new ApiSpecInfoUI();
|
||||
apiUI.setApiId(apiEntity.getEaiSvcName());
|
||||
apiList.add(apiUI);
|
||||
}
|
||||
}
|
||||
credentialUI.setApiList(apiList);
|
||||
|
||||
return credentialUI;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
package com.eactive.eai.rms.onl.manage.authserver.client;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 개발자포탈 정보 반영 결과 DTO
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class SyncResult {
|
||||
|
||||
/**
|
||||
* 반영 성공 여부
|
||||
*/
|
||||
private boolean success;
|
||||
|
||||
/**
|
||||
* 결과 메시지
|
||||
*/
|
||||
private String message;
|
||||
|
||||
/**
|
||||
* 반영 액션 타입
|
||||
*/
|
||||
private SyncAction action;
|
||||
|
||||
/**
|
||||
* 존재하지 않는 API 목록 (SKIPPED_INVALID_API인 경우)
|
||||
*/
|
||||
private List<String> invalidApis;
|
||||
|
||||
/**
|
||||
* 반영 액션 타입
|
||||
*/
|
||||
public enum SyncAction {
|
||||
/**
|
||||
* 신규 생성
|
||||
*/
|
||||
INSERTED,
|
||||
|
||||
/**
|
||||
* 기존 데이터 업데이트
|
||||
*/
|
||||
UPDATED,
|
||||
|
||||
/**
|
||||
* orgId 없어서 건너뜀
|
||||
*/
|
||||
SKIPPED_NO_ORG,
|
||||
|
||||
/**
|
||||
* 유효하지 않은 API 존재로 건너뜀
|
||||
*/
|
||||
SKIPPED_INVALID_API,
|
||||
|
||||
/**
|
||||
* 오류 발생
|
||||
*/
|
||||
ERROR
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user