Add API retrieval by organization code and enhance SSO user handling
- Implemented `getApisByOrgCode` method in `ObpApiService` to fetch APIs based on organization code. - Added corresponding endpoint in `ObpApiController`. - Updated `SsoController` to handle user creation without synchronization for existing users. - Introduced new properties for SSO synchronization settings in `KjbProperty`.
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
|
||||
<%@ taglib uri="http://www.springframework.org/tags" prefix="spring"%>
|
||||
<%@ include file="/jsp/common/include/localemessage.jsp" %>
|
||||
<c:set var="themeColor" value="<%=System.getProperty(\"theme.color\")%>" scope="session" />
|
||||
|
||||
<%
|
||||
String topPage = request.getContextPath() + StringUtils.defaultString((String) request.getAttribute("topPage"), "/top_04.do");
|
||||
|
||||
+8
@@ -4,7 +4,15 @@ import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||
import com.eactive.eai.data.jpa.BaseRepository;
|
||||
import com.eactive.eai.rms.data.EMSDataSource;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@EMSDataSource
|
||||
public interface PortalOrgRepository extends BaseRepository<PortalOrg, String> {
|
||||
|
||||
/**
|
||||
* 기관코드로 기관 조회
|
||||
* @param orgCode 기관코드 (OBP 파트너코드)
|
||||
* @return 기관 정보
|
||||
*/
|
||||
Optional<PortalOrg> findByOrgCode(String orgCode);
|
||||
}
|
||||
|
||||
@@ -106,39 +106,49 @@ public class SsoController implements InterceptorSkipController {
|
||||
return "redirect:/loginForm.do";
|
||||
}
|
||||
|
||||
// 기본 정보
|
||||
Properties info = ssoModule.getUserInfos(ssoId);
|
||||
// 확장 정보
|
||||
Properties extendedInfo = ssoModule.getUserExFields(ssoId);
|
||||
if (prop.isSsoSyncInfo()) {
|
||||
// 기본 정보
|
||||
Properties info = ssoModule.getUserInfos(ssoId);
|
||||
// 확장 정보
|
||||
Properties extendedInfo = ssoModule.getUserExFields(ssoId);
|
||||
|
||||
// 필수 필드 검증
|
||||
try {
|
||||
validateRequiredFields(info, extendedInfo);
|
||||
} catch (IllegalStateException e) {
|
||||
log.warn("SSO 필수 필드 검증 실패: {}", e.getMessage());
|
||||
session.setAttribute("resultMsg", e.getMessage());
|
||||
return "redirect:/loginForm.do";
|
||||
// 필수 필드 검증
|
||||
try {
|
||||
validateRequiredFields(info, extendedInfo);
|
||||
} catch (IllegalStateException e) {
|
||||
log.warn("SSO 필수 필드 검증 실패: {}", e.getMessage());
|
||||
session.setAttribute("resultMsg", e.getMessage());
|
||||
return "redirect:/loginForm.do";
|
||||
}
|
||||
|
||||
// 사용자 정보 로깅 (개인정보 마스킹 처리)
|
||||
String userId = info.getProperty("USERID");
|
||||
String name = info.getProperty("NAME");
|
||||
String email = info.getProperty("EMAIL");
|
||||
String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
|
||||
|
||||
log.info("SSO 로그인 시도 - userId: {}", userId);
|
||||
log.debug("SSO 사용자 정보 - userId: {}, name: {}, phone: {}, email: {}",
|
||||
userId,
|
||||
MaskingUtils.maskName(name),
|
||||
maskPhoneNumber(cellPhoneNo),
|
||||
maskEmail(email));
|
||||
|
||||
// 사용자 생성 또는 업데이트
|
||||
UserInfo userInfo = findOrCreateUser(info, extendedInfo);
|
||||
|
||||
// 로그인 세션 설정 (MainController 위임)
|
||||
log.info("SSO 로그인 성공 - userId: {}", userId);
|
||||
return mainController.setupSsoLoginSession(req, userInfo);
|
||||
} else {
|
||||
// 동기화 비활성화 모드: 기존 사용자는 업데이트 없이, 신규 사용자는 최소 정보로 생성
|
||||
log.info("SSO 동기화 비활성화 모드로 로그인 처리 - ssoId: {}", ssoId);
|
||||
|
||||
UserInfo userInfo = findOrCreateUserWithoutSync(ssoId);
|
||||
|
||||
log.info("SSO 로그인 성공 (동기화 비활성화 모드) - userId: {}", ssoId);
|
||||
return mainController.setupSsoLoginSession(req, userInfo);
|
||||
}
|
||||
|
||||
// 사용자 정보 로깅 (개인정보 마스킹 처리)
|
||||
String userId = info.getProperty("USERID");
|
||||
String name = info.getProperty("NAME");
|
||||
String email = info.getProperty("EMAIL");
|
||||
String cellPhoneNo = extendedInfo != null ? extendedInfo.getProperty("CELLPHONENO") : null;
|
||||
|
||||
log.info("SSO 로그인 시도 - userId: {}", userId);
|
||||
log.debug("SSO 사용자 정보 - userId: {}, name: {}, phone: {}, email: {}",
|
||||
userId,
|
||||
MaskingUtils.maskName(name),
|
||||
maskPhoneNumber(cellPhoneNo),
|
||||
maskEmail(email));
|
||||
|
||||
// 사용자 생성 또는 업데이트
|
||||
UserInfo userInfo = findOrCreateUser(info, extendedInfo);
|
||||
|
||||
// 로그인 세션 설정 (MainController 위임)
|
||||
log.info("SSO 로그인 성공 - userId: {}", userId);
|
||||
return mainController.setupSsoLoginSession(req, userInfo);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,6 +184,52 @@ public class SsoController implements InterceptorSkipController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 사용자 조회 또는 생성 (동기화 비활성화 모드)
|
||||
* - 기존 사용자: 정보 업데이트 없이 그대로 반환
|
||||
* - 신규 사용자: userId를 username으로 사용하여 최소 정보로 생성
|
||||
*/
|
||||
private UserInfo findOrCreateUserWithoutSync(String ssoId) throws Exception {
|
||||
// 대소문자 구분 없이 검색
|
||||
Optional<UserInfo> existingUser = userInfoService.findByUserIdIgnoreCase(ssoId);
|
||||
|
||||
if (existingUser.isPresent()) {
|
||||
log.debug("동기화 비활성화 모드 - 기존 사용자 발견, 정보 업데이트 없이 로그인 처리: {}", ssoId);
|
||||
return existingUser.get();
|
||||
} else {
|
||||
return createNewUserWithMinimalInfo(ssoId);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 최소 정보로 신규 사용자 생성 (동기화 비활성화 모드)
|
||||
* - username을 userId와 동일하게 설정
|
||||
*/
|
||||
private UserInfo createNewUserWithMinimalInfo(String userId) throws Exception {
|
||||
UserInfo userInfo = new UserInfo();
|
||||
userInfo.setUserid(userId);
|
||||
userInfo.setUsername(userId); // username = userId
|
||||
userInfo.setPassword(Seed.encrypt("!" + userId));
|
||||
userInfo.setRoleidnfiname(CommonConstants.DEPT_DEVELOPER);
|
||||
|
||||
userInfoService.save(userInfo);
|
||||
|
||||
// 기본 역할 할당
|
||||
String roleId = monitoringContext.getStringProperty(
|
||||
MonitoringContext.USER_DEFAULT_RULE, "newbie");
|
||||
UserRole userRole = new UserRole();
|
||||
userRole.setId(new UserRoleId(userId, roleId));
|
||||
userRoleService.save(userRole);
|
||||
|
||||
// 서비스 타입 할당
|
||||
DataSourceTypeManager.getDynamicDataSourceTypes().stream()
|
||||
.map(DataSourceType::getName)
|
||||
.forEach(type -> userServiceTypeService.insertUserServiceType(userId, type));
|
||||
|
||||
log.info("동기화 비활성화 모드 - 신규 사용자 생성 완료 (최소 정보): {}", userId);
|
||||
return userInfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* 신규 사용자 생성
|
||||
*/
|
||||
|
||||
@@ -6,6 +6,7 @@ import com.eactive.eai.rms.onl.apim.common.BaseRestController;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
@@ -42,7 +43,8 @@ public class ObpApiController extends BaseRestController {
|
||||
)
|
||||
@ResponseBody
|
||||
public String getApis(
|
||||
@RequestParam(value = "pretty", required = false) Boolean pretty) {
|
||||
@RequestParam(value = "pretty", required = false) Boolean pretty
|
||||
) {
|
||||
log.debug("OBP API 목록 조회 요청: pretty={}", pretty);
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
@@ -50,6 +52,7 @@ public class ObpApiController extends BaseRestController {
|
||||
DataSourceContextHolder.setDataSourceType(
|
||||
DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));
|
||||
|
||||
|
||||
try {
|
||||
List<ObpApiDTO> apis = obpApiService.findAllApis();
|
||||
|
||||
@@ -66,4 +69,46 @@ public class ObpApiController extends BaseRestController {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 기관코드별 API 목록 조회
|
||||
*
|
||||
* <p>해당 기관의 활성 앱(appstatus='1')이 사용하는 API만 반환</p>
|
||||
*
|
||||
* @param orgCode 기관코드 (OBP 파트너코드)
|
||||
* @param pretty true면 JSON 들여쓰기 적용
|
||||
* @return JSON Array (기관 미존재 시 빈 배열)
|
||||
*/
|
||||
@RequestMapping(
|
||||
value = "/kjb/{orgCode}/apis.json",
|
||||
produces = JSON_CONTENT_TYPE
|
||||
)
|
||||
@ResponseBody
|
||||
public String getApisByOrgCode(
|
||||
@PathVariable("orgCode") String orgCode,
|
||||
@RequestParam(value = "pretty", required = false) Boolean pretty
|
||||
) {
|
||||
log.debug("OBP API 목록 조회 요청 (기관별): orgCode={}, pretty={}", orgCode, pretty);
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
// APIGW 데이터소스 강제 설정
|
||||
DataSourceContextHolder.setDataSourceType(
|
||||
DataSourceTypeManager.getDataSourceType(DataSourceTypeManager.APIGW));
|
||||
|
||||
try {
|
||||
List<ObpApiDTO> apis = obpApiService.findApisByOrgCode(orgCode);
|
||||
|
||||
String json = toJson(apis, pretty);
|
||||
|
||||
long elapsed = System.currentTimeMillis() - startTime;
|
||||
log.info("OBP API 목록 조회 완료 (기관별): orgCode={}, count={}, size={}, elapsed={}ms",
|
||||
orgCode, apis.size(), getFormattedJsonSize(json), elapsed);
|
||||
|
||||
return json;
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("OBP API 목록 조회 실패 (기관별): orgCode={}", orgCode, e);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package com.eactive.eai.rms.onl.apim.obp;
|
||||
|
||||
import com.eactive.apim.portal.app.entity.Credential;
|
||||
import com.eactive.apim.portal.app.repository.CredentialRepository;
|
||||
import com.eactive.apim.portal.apispec.entity.ApiSpecInfo;
|
||||
import com.eactive.apim.portal.portalorg.entity.PortalOrg;
|
||||
import com.eactive.eai.data.entity.onl.message.QEAIMessageEntity;
|
||||
import com.eactive.eai.data.entity.onl.stdmessage.QStandardMessageInfo;
|
||||
import com.eactive.eai.rms.data.entity.onl.apim.portalorg.PortalOrgRepository;
|
||||
import com.querydsl.core.Tuple;
|
||||
import com.querydsl.jpa.impl.JPAQueryFactory;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@@ -9,7 +14,10 @@ import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -23,6 +31,14 @@ public class ObpApiService {
|
||||
@PersistenceContext
|
||||
private EntityManager entityManager;
|
||||
|
||||
private final PortalOrgRepository portalOrgRepository;
|
||||
private final CredentialRepository credentialRepository;
|
||||
|
||||
public ObpApiService(PortalOrgRepository portalOrgRepository, CredentialRepository credentialRepository) {
|
||||
this.portalOrgRepository = portalOrgRepository;
|
||||
this.credentialRepository = credentialRepository;
|
||||
}
|
||||
|
||||
private JPAQueryFactory getQueryFactory() {
|
||||
return new JPAQueryFactory(entityManager);
|
||||
}
|
||||
@@ -88,4 +104,60 @@ public class ObpApiService {
|
||||
.authType(authtype)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* 기관코드에 해당하는 법인이 이용하는 API 목록 조회
|
||||
*
|
||||
* <p>활성 앱(appstatus='1')의 API만 조회</p>
|
||||
*
|
||||
* @param orgCode 기관코드 (OBP 파트너코드)
|
||||
* @return API 목록 (기관 미존재 시 빈 리스트)
|
||||
*/
|
||||
public List<ObpApiDTO> findApisByOrgCode(String orgCode) {
|
||||
// 1. 기관코드로 기관 조회
|
||||
Optional<PortalOrg> orgOpt = portalOrgRepository.findByOrgCode(orgCode);
|
||||
if (!orgOpt.isPresent()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
PortalOrg org = orgOpt.get();
|
||||
|
||||
// 2. 해당 기관의 활성 앱 조회 (appstatus='1')
|
||||
List<Credential> activeApps = credentialRepository.findActiveAppsByOrgIds(
|
||||
Collections.singletonList(org.getId()));
|
||||
if (activeApps.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 3. 앱들의 API ID 목록 수집
|
||||
Set<String> apiIds = activeApps.stream()
|
||||
.flatMap(app -> app.getApiList().stream())
|
||||
.map(ApiSpecInfo::getApiId)
|
||||
.collect(Collectors.toSet());
|
||||
if (apiIds.isEmpty()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
// 4. 해당 API만 조회
|
||||
QEAIMessageEntity he01 = QEAIMessageEntity.eAIMessageEntity;
|
||||
QStandardMessageInfo hs04 = QStandardMessageInfo.standardMessageInfo;
|
||||
|
||||
List<Tuple> results = getQueryFactory()
|
||||
.select(
|
||||
he01.eaisvcname,
|
||||
he01.eaisvcdesc,
|
||||
he01.useyn,
|
||||
he01.authtype,
|
||||
hs04.apifullpath
|
||||
)
|
||||
.from(he01)
|
||||
.leftJoin(hs04).on(he01.eaisvcname.eq(hs04.eaisvcname))
|
||||
.where(he01.eaisvcname.in(apiIds))
|
||||
.orderBy(he01.eaisvcname.asc())
|
||||
.fetch();
|
||||
|
||||
return results.stream()
|
||||
.map(this::toDto)
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user