# Conflicts:
eapim-portal CI / build (push) Has been cancelled
eapim-portal Test / test (push) Has been cancelled

#	src/main/resources/static/css/main.css.map
This commit is contained in:
Rinjae
2026-07-13 13:29:54 +09:00
parent 3e403788e5
commit 778d579ada
56 changed files with 3330 additions and 9285 deletions
@@ -0,0 +1,95 @@
package com.eactive.apim.portal.djb.testbed.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.when;
import com.eactive.apim.portal.djb.testbed.config.DjbTestbedGatewayProperty;
import com.eactive.apim.portal.djb.testbed.enums.DjbAuthType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
class DjbSwaggerSpecEnricherTest {
@Mock
private DjbTestbedGatewayProperty gatewayProperty;
private final ObjectMapper objectMapper = new ObjectMapper();
private DjbSwaggerSpecEnricher enricher;
@BeforeEach
void setUp() {
enricher = new DjbSwaggerSpecEnricher(objectMapper, gatewayProperty);
}
@Test
void oauth_injects_apiKey_scheme_with_oauth_header_and_preserves_original() throws Exception {
when(gatewayProperty.oauthHeader()).thenReturn("X-AUTH-TOKEN");
String spec = "{\"openapi\":\"3.0.0\",\"info\":{\"title\":\"t\"},"
+ "\"paths\":{\"/a\":{\"get\":{\"x-original-api-id\":\"API1\"}}}}";
String result = enricher.enrich(spec, DjbAuthType.OAUTH);
JsonNode root = objectMapper.readTree(result);
JsonNode scheme = root.path("components").path("securitySchemes").path("djbOAuth");
assertEquals("apiKey", scheme.path("type").asText());
assertEquals("header", scheme.path("in").asText());
assertEquals("X-AUTH-TOKEN", scheme.path("name").asText());
assertTrue(root.path("security").get(0).has("djbOAuth"));
// 원본 paths / x- 확장 보존
assertEquals("API1", root.path("paths").path("/a").path("get").path("x-original-api-id").asText());
}
@Test
void apiKey_injects_apiKey_scheme_with_api_key_header() throws Exception {
when(gatewayProperty.apiKeyHeader()).thenReturn("X-DJB-API-Key");
String spec = "{\"openapi\":\"3.0.0\",\"paths\":{}}";
String result = enricher.enrich(spec, DjbAuthType.API_KEY);
JsonNode root = objectMapper.readTree(result);
JsonNode scheme = root.path("components").path("securitySchemes").path("djbApiKey");
assertEquals("apiKey", scheme.path("type").asText());
assertEquals("header", scheme.path("in").asText());
assertEquals("X-DJB-API-Key", scheme.path("name").asText());
assertTrue(root.path("security").get(0).has("djbApiKey"));
}
@Test
void none_strips_security_and_schemes_but_preserves_paths() throws Exception {
// 저장 spec 에 빈 securitySchemes + 글로벌 security 가 남아 있어도 NONE 은 제거한다.
String spec = "{\"openapi\":\"3.0.0\",\"security\":[{\"djbOAuth\":[]}],"
+ "\"components\":{\"securitySchemes\":{},\"schemas\":{\"X\":{}}},"
+ "\"paths\":{\"/a\":{\"get\":{\"x-original-api-id\":\"API1\"}}}}";
String result = enricher.enrich(spec, DjbAuthType.NONE);
JsonNode root = objectMapper.readTree(result);
// 인증 흔적 제거 → Swagger UI Authorize 버튼 미표시.
assertFalse(root.has("security"));
assertFalse(root.path("components").has("securitySchemes"));
// 그 외(components.schemas, paths, x- 확장)는 보존.
assertTrue(root.path("components").has("schemas"));
assertEquals("API1", root.path("paths").path("/a").path("get").path("x-original-api-id").asText());
}
@Test
void swagger2_falls_back_to_securityDefinitions() throws Exception {
when(gatewayProperty.apiKeyHeader()).thenReturn("X-DJB-API-Key");
String spec = "{\"swagger\":\"2.0\",\"paths\":{}}";
String result = enricher.enrich(spec, DjbAuthType.API_KEY);
JsonNode root = objectMapper.readTree(result);
assertEquals("X-DJB-API-Key",
root.path("securityDefinitions").path("djbApiKey").path("name").asText());
assertFalse(root.has("components"));
}
}
@@ -0,0 +1,205 @@
package com.eactive.apim.portal.djb.testbed.service;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import com.eactive.apim.gateway.data.eaimessage.EAIMessageRepository;
import com.eactive.apim.portal.app.entity.Credential;
import com.eactive.apim.portal.app.repository.CredentialRepository;
import com.eactive.apim.portal.apps.user.dto.PortalOrgDTO;
import com.eactive.apim.portal.common.user.PortalAuthenticatedUser;
import com.eactive.apim.portal.common.util.SecurityUtil;
import com.eactive.apim.portal.djb.testbed.config.DjbTestbedGatewayProperty;
import com.eactive.apim.portal.djb.testbed.dto.DjbCredentialSecretDto;
import com.eactive.apim.portal.djb.testbed.dto.DjbTestbedContextDto;
import com.eactive.apim.portal.djb.testbed.enums.DjbAuthType;
import com.eactive.apim.portal.djb.testbed.enums.DjbGatewayMode;
import com.eactive.apim.portal.djb.testbed.exception.DjbUnsupportedAuthTypeException;
import com.eactive.apim.portal.portaluser.entity.PortalUserEnums.RoleCode;
import com.eactive.eai.data.entity.onl.message.EAIMessageEntity;
import java.util.Collections;
import java.util.Optional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.junit.jupiter.MockitoSettings;
import org.mockito.quality.Strictness;
import org.springframework.security.access.AccessDeniedException;
@ExtendWith(MockitoExtension.class)
@MockitoSettings(strictness = Strictness.LENIENT)
class DjbTestbedAuthServiceTest {
@Mock private CredentialRepository credentialRepository;
@Mock private EAIMessageRepository eaiMessageRepository;
@Mock private DjbTestbedGatewayProperty gatewayProperty;
private DjbTestbedAuthService service;
private static final String ORG_ID = "ORG1";
private static final String CLIENT_ID = "CID";
private static final String API_ID = "API1";
@BeforeEach
void setUp() {
service = new DjbTestbedAuthService(credentialRepository, eaiMessageRepository, gatewayProperty);
// 게이트웨이 정보(buildContext 모든 분기에서 구성)
when(gatewayProperty.resolveGatewayMode()).thenReturn(DjbGatewayMode.PORTAL_MOCK);
when(gatewayProperty.baseUrl()).thenReturn("PortalMock");
when(gatewayProperty.resolveTokenUrl(anyString())).thenReturn("http://localhost/api/v1/oauth/token");
when(gatewayProperty.apiKeyHeader()).thenReturn("X-DJB-API-Key");
when(gatewayProperty.oauthHeader()).thenReturn("X-AUTH-TOKEN");
}
private PortalAuthenticatedUser user(RoleCode roleCode) {
PortalAuthenticatedUser u = new PortalAuthenticatedUser();
u.setRoleCode(roleCode);
return u;
}
private PortalOrgDTO org() {
PortalOrgDTO o = new PortalOrgDTO();
o.setId(ORG_ID);
return o;
}
@Test
void buildContext_anonymous() {
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(false);
DjbTestbedContextDto ctx = service.buildContext("http://localhost:8080");
assertFalse(ctx.isEligible());
assertEquals("ANONYMOUS", ctx.getReason());
}
}
@Test
void buildContext_individualUser() {
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(true);
sec.when(SecurityUtil::getPortalAuthenticatedUser).thenReturn(user(RoleCode.ROLE_USER));
DjbTestbedContextDto ctx = service.buildContext("http://localhost:8080");
assertFalse(ctx.isEligible());
assertEquals("INDIVIDUAL_USER", ctx.getReason());
}
}
@Test
void buildContext_noCredential() {
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(true);
sec.when(SecurityUtil::getPortalAuthenticatedUser).thenReturn(user(RoleCode.ROLE_CORP_USER));
sec.when(SecurityUtil::getUserOrg).thenReturn(org());
when(credentialRepository.findAllByOrgid(ORG_ID)).thenReturn(Collections.emptyList());
DjbTestbedContextDto ctx = service.buildContext("http://localhost:8080");
assertFalse(ctx.isEligible());
assertEquals("NO_CREDENTIAL", ctx.getReason());
}
}
@Test
void buildContext_eligible_onlyActiveApps() {
Credential active = new Credential();
active.setClientid(CLIENT_ID);
active.setClientname("APP");
active.setAppstatus("1");
Credential blocked = new Credential();
blocked.setClientid("CID2");
blocked.setAppstatus("0");
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(true);
sec.when(SecurityUtil::getPortalAuthenticatedUser).thenReturn(user(RoleCode.ROLE_CORP_MANAGER));
sec.when(SecurityUtil::getUserOrg).thenReturn(org());
when(credentialRepository.findAllByOrgid(ORG_ID)).thenReturn(java.util.Arrays.asList(active, blocked));
DjbTestbedContextDto ctx = service.buildContext("http://localhost:8080");
assertTrue(ctx.isEligible());
assertEquals(1, ctx.getCredentials().size());
assertEquals(CLIENT_ID, ctx.getCredentials().get(0).getClientId());
}
}
@Test
void getCredentialSecret_success() {
Credential cred = new Credential();
cred.setClientid(CLIENT_ID);
cred.setClientsecret("SECRET");
EAIMessageEntity msg = Mockito.mock(EAIMessageEntity.class);
when(msg.getAuthtype()).thenReturn("oauth");
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(true);
sec.when(SecurityUtil::getPortalAuthenticatedUser).thenReturn(user(RoleCode.ROLE_CORP_USER));
sec.when(SecurityUtil::getUserOrg).thenReturn(org());
when(credentialRepository.findByClientidAndOrgid(CLIENT_ID, ORG_ID)).thenReturn(Optional.of(cred));
when(eaiMessageRepository.findById(API_ID)).thenReturn(Optional.of(msg));
DjbCredentialSecretDto dto = service.getCredentialSecret(CLIENT_ID, API_ID);
assertEquals("SECRET", dto.getClientSecret());
assertEquals(DjbAuthType.OAUTH, dto.getAuthType());
}
}
@Test
void getCredentialSecret_notOwned_throwsAccessDenied() {
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(true);
sec.when(SecurityUtil::getPortalAuthenticatedUser).thenReturn(user(RoleCode.ROLE_CORP_USER));
sec.when(SecurityUtil::getUserOrg).thenReturn(org());
when(credentialRepository.findByClientidAndOrgid(CLIENT_ID, ORG_ID)).thenReturn(Optional.empty());
assertThrows(AccessDeniedException.class, () -> service.getCredentialSecret(CLIENT_ID, API_ID));
}
}
@Test
void getCredentialSecret_anonymous_throwsAccessDenied() {
try (MockedStatic<SecurityUtil> sec = Mockito.mockStatic(SecurityUtil.class)) {
sec.when(SecurityUtil::isAuthenticated).thenReturn(false);
assertThrows(AccessDeniedException.class, () -> service.getCredentialSecret(CLIENT_ID, API_ID));
}
}
@Test
void resolveAuthType_apiKey() {
EAIMessageEntity msg = Mockito.mock(EAIMessageEntity.class);
when(msg.getAuthtype()).thenReturn("api_key");
when(eaiMessageRepository.findById(API_ID)).thenReturn(Optional.of(msg));
assertEquals(DjbAuthType.API_KEY, service.resolveAuthType(API_ID));
}
@Test
void resolveAuthType_none_returnsNone() {
EAIMessageEntity msg = Mockito.mock(EAIMessageEntity.class);
when(msg.getAuthtype()).thenReturn("none");
when(eaiMessageRepository.findById(API_ID)).thenReturn(Optional.of(msg));
assertEquals(DjbAuthType.NONE, service.resolveAuthType(API_ID));
}
@Test
void resolveAuthType_missing_throwsUnsupported() {
when(eaiMessageRepository.findById("APIX")).thenReturn(Optional.empty());
assertThrows(DjbUnsupportedAuthTypeException.class, () -> service.resolveAuthType("APIX"));
}
}