refs #702: externalize HMM structured data catalog

This commit is contained in:
devmrko
2026-07-23 10:43:54 +09:00
parent eb5105fe72
commit 9e3840a4d7
23 changed files with 495 additions and 136 deletions

View File

@@ -1,8 +1,13 @@
package com.cloudhandson.vpdbackoffice.service;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import com.cloudhandson.vpdbackoffice.mapper.MaskingRuleMapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
class MaskingPolicySynchronizerTest {
@@ -23,8 +28,16 @@ class MaskingPolicySynchronizerTest {
}
@Test
void kbContractsPremiumPolicyIsManagedByBackoffice() {
assertThat(MaskingPolicySynchronizer.managedPolicyName("KB_CONTRACTS"))
.isEqualTo("KB_CONTRACT_PREMIUM_REDACT");
void hmmEmployeePolicyComesFromTheSharedJsonCatalog() {
var catalogProvider = new StructuredDataCatalogProvider(
new ObjectMapper(), new ClassPathResource("config/structured-data-catalog.json"));
var synchronizer = new MaskingPolicySynchronizer(
mock(JdbcTemplate.class), mock(MaskingRuleMapper.class), catalogProvider);
assertThat(synchronizer.owner()).isEqualTo("ADMIN");
assertThat(synchronizer.managedPolicyName("HMM_HR_EMPLOYEES"))
.isEqualTo("HMM_EMPLOYEE_PII_REDACT");
assertThat(synchronizer.managedObjectNames())
.doesNotContain("KB_CUSTOMERS", "KB_CLAIMS", "KB_CONTRACTS");
}
}

View File

@@ -4,25 +4,34 @@ import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.jdbc.core.JdbcTemplate;
class StructuredDataServiceTest {
private final StructuredDataService service = new StructuredDataService(mock(JdbcTemplate.class));
private final StructuredDataCatalogProvider catalogProvider = new StructuredDataCatalogProvider(
new ObjectMapper(), new ClassPathResource("config/structured-data-catalog.json"));
private final StructuredDataService service = new StructuredDataService(
mock(JdbcTemplate.class), catalogProvider);
@Test
void exposesOnlyTheSevenApprovedStructuredTables() {
void exposesOnlyTheHMMTablesFromTheJsonCatalog() {
assertThat(service.catalog().sourceName()).isEqualTo("HMMAIPOC");
assertThat(service.owner()).isEqualTo("ADMIN");
assertThat(service.tables())
.extracting(table -> table.tableName())
.containsExactly(
"KB_CUSTOMERS",
"KB_PRODUCTS",
"KB_CONTRACTS",
"KB_COVERAGES",
"KB_CLAIMS",
"KB_EXTERNAL_HOLDINGS",
"KB_STAKEHOLDERS");
"HMM_ORG_TEAMS",
"HMM_HR_EMPLOYEES",
"HMM_LEAVE_BALANCES",
"HMM_LEAVE_REQUESTS",
"HMM_ATTENDANCE_DAILY",
"HMM_HR_TERMS");
assertThat(service.previewSql(service.requireTable("employees")))
.isEqualTo("SELECT * FROM \"ADMIN\".\"HMM_HR_EMPLOYEES\" WHERE ROWNUM <= ?");
}
@Test
@@ -31,4 +40,25 @@ class StructuredDataServiceTest {
.isInstanceOf(AppException.class)
.hasMessage("선택할 수 없는 정형 데이터 테이블입니다.");
}
@Test
void rejectsUnsafeOracleIdentifiersInAnExternalCatalog() {
String unsafeJson = """
{
"sourceName": "demo",
"owner": "ADMIN; DROP USER X",
"pageHelp": "help",
"catalogDescription": "description",
"rowLimit": 10,
"tables": [
{"key":"employees","tableName":"EMPLOYEES","businessName":"직원","description":"직원"}
]
}
""";
assertThatThrownBy(() -> new StructuredDataCatalogProvider(
new ObjectMapper(), new ByteArrayResource(unsafeJson.getBytes())))
.isInstanceOf(IllegalStateException.class)
.hasMessageContaining("owner 형식이 올바르지 않습니다");
}
}