package com.cloudhandson.vpdbackoffice.web; import static org.assertj.core.api.Assertions.assertThat; import com.cloudhandson.vpdbackoffice.domain.masking.ColumnMaskingRule; import com.cloudhandson.vpdbackoffice.domain.masking.MaskingRule; import com.cloudhandson.vpdbackoffice.domain.masking.MaskingPolicyStatus; import com.cloudhandson.vpdbackoffice.domain.masking.MaskingTemplate; import com.cloudhandson.vpdbackoffice.domain.masking.UserMaskingRule; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedColumn; import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject; import com.cloudhandson.vpdbackoffice.domain.user.AppUser; import java.nio.file.Path; import java.util.List; import java.util.Locale; import java.util.Map; import org.junit.jupiter.api.Test; import org.thymeleaf.context.Context; import org.thymeleaf.spring6.SpringTemplateEngine; import org.thymeleaf.templateresolver.FileTemplateResolver; class MaskingRuleTemplateRenderTest { @Test void rendersRuleRegistrationAndUserExceptionPages() { var resolver = new FileTemplateResolver(); resolver.setPrefix(Path.of("src/main/resources/templates").toAbsolutePath() + "/"); resolver.setSuffix(".html"); resolver.setTemplateMode("HTML"); resolver.setCacheable(false); var engine = new SpringTemplateEngine(); engine.setTemplateResolver(resolver); var object = new ProtectedObject(7L, "POC_2", "KB_CUSTOMERS", "kb/customers", "Y"); var contractObject = new ProtectedObject(8L, "POC_2", "KB_CONTRACTS", "kb/contracts", "Y"); var column = new ProtectedColumn(11L, 7L, "RRN_MASKED", "Y", null, "RESTRICTED", "NULLIFY"); var rule = new MaskingRule(1L, "KB_RRN_STANDARD", "주민번호 기본 마스킹", "RRN_PARTIAL", "테스트", "Y"); var columnRule = new ColumnMaskingRule(11L, 7L, "POC_2", "KB_CUSTOMERS", "RRN_MASKED", 1L, "KB_RRN_STANDARD", "주민번호 기본 마스킹", "RRN_PARTIAL", "Y"); var context = new Context(Locale.KOREAN); context.setVariable("_csrf", new CsrfFixture("_csrf", "test-token")); context.setVariable("templates", List.of(MaskingTemplate.values())); context.setVariable("rules", List.of(rule)); context.setVariable("columnRules", List.of(columnRule)); var status = new MaskingPolicyStatus( "POC_2", "KB_CUSTOMERS", "KB_CUSTOMER_PII_REDACT", "YES", 1, 1, 0, 0 ); context.setVariable("policyStatuses", List.of(status)); context.setVariable("policyStatusByObjectName", Map.of("KB_CUSTOMERS", status)); context.setVariable("objects", List.of(object, contractObject)); context.setVariable("maskingTargetObjects", List.of(object, contractObject)); context.setVariable("sensitiveColumnsByObject", Map.of(7L, List.of(column), 8L, List.of())); context.setVariable("availableMaskingColumnsByObject", Map.of(7L, List.of("CUST_NM"), 8L, List.of("PREMIUM"))); String rulesPage = engine.process("masking-rules", context); assertThat(rulesPage) .contains("사전 정의 마스킹 방식") .contains("민감 컬럼에 기본 규칙 연결") .contains("DBMS_REDACT.REGEXP") .contains("컬럼 원문 표시 허용 사용자") .contains("현재 DB 정책 동기화") .contains("자동 동기화") .contains("DB Redaction 컬럼") .contains("레거시 VPD 컬럼 제어") .contains("마스킹 대상 컬럼 추가") .contains("POC_2.KB_CONTRACTS.PREMIUM") .contains("KB_CUSTOMER_PII_REDACT") .contains("적용됨"); context.setVariable("users", List.of(new AppUser(2L, "KB_VPD_ADMIN", "ADMIN", "SEC", "N", "Y"))); context.setVariable("userRules", List.of(new UserMaskingRule(2L, "KB_VPD_ADMIN", 11L, "POC_2", "KB_CUSTOMERS", "RRN_MASKED", "주민번호 기본 마스킹", "RRN_PARTIAL", "UNMASK", "Y"))); String userPage = engine.process("user-masking-rules", context); assertThat(userPage) .contains("컬럼 원문 표시 허용 사용자 추가") .contains("원문 표시 허용") .contains("행 접근 여부는 변경하지 않습니다") .contains("선택한 컬럼의 실제 적용 결과") .contains("data-masking-exception-preview") .contains("MR_11"); } private record CsrfFixture(String parameterName, String token) { } }