[UX] #605 make permission wizard safety review actionable

This commit is contained in:
devmrko
2026-06-30 20:39:54 +09:00
parent 1766696ab4
commit f162851bc6
7 changed files with 289 additions and 25 deletions

View File

@@ -85,11 +85,20 @@ class GuidedFlowTemplateTest {
@Test
void permissionWizardExplainsTagRulesAndOrSemantics() throws IOException {
String html = template("permissions.html");
String javascript = Files.readString(Path.of("src/main/resources/static/js/app.js"));
assertThat(html)
.contains("value=\"TAG\">특정 기술 태그")
.contains("TECH_TAG")
.contains("태그를 여러 개 추가하면");
.contains("태그를 여러 개 추가하면")
.contains("data-wizard-validation")
.contains("다른 조건 규칙은 한 권한에 함께 저장할 수 없습니다")
.contains("저장 영향")
.contains("되돌리기");
assertThat(javascript)
.contains("validatePermissionWizardStep")
.contains("ALL 규칙은 다른 조건 규칙과 함께 저장할 수 없습니다")
.contains("movePermissionWizard");
}
@Test

View File

@@ -0,0 +1,58 @@
package com.cloudhandson.vpdbackoffice.web;
import static org.assertj.core.api.Assertions.assertThat;
import com.cloudhandson.vpdbackoffice.domain.permission.AppRole;
import com.cloudhandson.vpdbackoffice.domain.protectedobject.DatabaseObjectOption;
import com.cloudhandson.vpdbackoffice.domain.protectedobject.ProtectedObject;
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 PermissionTemplateRenderTest {
@Test
void rendersThePermissionSafetyReviewWithLayoutFragments() {
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 role = new AppRole(30L, "ALL_DOC_ROLE", "전체 문서 역할", "CONFIDENTIAL");
var object = new ProtectedObject(3L, "ADMIN", "CB_VECTOR_SEARCH_DOCUMENTS", "vector/search", "Y");
var context = new Context(Locale.KOREAN);
context.setVariable("_csrf", new CsrfFixture("_csrf", "test-token"));
context.setVariable("roles", List.of(role));
context.setVariable("objects", List.of(object));
context.setVariable("columnsByObject", Map.of(3L, List.of("CHUNK_TEXT", "TECH_TAG")));
context.setVariable("maskableColumnsByObject", Map.of(3L, List.of("CHUNK_TEXT")));
context.setVariable("maskableColumnLabelsByObject", Map.of(3L, List.of("CHUNK_TEXT [CONFIDENTIAL/NULLIFY]")));
context.setVariable("directUsersByRole", Map.of(30L, List.of("김어드민")));
context.setVariable("groupsByRole", Map.of(30L, List.of("OPS / 운영")));
context.setVariable("groupUsersByRole", Map.of(30L, List.of("박파이넨스")));
context.setVariable("dbObjects", List.of(new DatabaseObjectOption("ADMIN", "BOARD_POSTS", "TABLE")));
context.setVariable("permissions", List.of());
context.setVariable("lastPermissionByPermissionId", Map.of());
String rendered = engine.process("permissions", context);
assertThat(rendered)
.contains("권한을 적용할 역할 선택")
.contains("권한을 적용할 보호 객체 선택")
.contains("data-wizard-validation")
.contains("저장 영향")
.contains("되돌리기")
.contains("김어드민");
}
private record CsrfFixture(String parameterName, String token) {
}
}