# Conflicts:
# src/main/resources/static/css/main.css.map
This commit is contained in:
+95
@@ -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"));
|
||||
}
|
||||
}
|
||||
+205
@@ -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"));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user