Consolidate data access control backoffice updates
This commit is contained in:
@@ -1,12 +1,15 @@
|
||||
package com.cloudhandson.vpdbackoffice.web;
|
||||
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyCreateCommand;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyView;
|
||||
import com.cloudhandson.vpdbackoffice.service.AppException;
|
||||
import com.cloudhandson.vpdbackoffice.service.VpdPolicyService;
|
||||
import java.util.List;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
@@ -17,6 +20,7 @@ import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
@Controller
|
||||
public class VpdPolicyController {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(VpdPolicyController.class);
|
||||
private final VpdPolicyService vpdPolicyService;
|
||||
|
||||
public VpdPolicyController(VpdPolicyService vpdPolicyService) {
|
||||
@@ -28,7 +32,7 @@ public class VpdPolicyController {
|
||||
@RequestParam(required = false) String schemaOwner,
|
||||
Model model
|
||||
) {
|
||||
populatePolicyModel(schemaOwner, model);
|
||||
populatePolicyModel(schemaOwner, false, model);
|
||||
return "vpd-policies";
|
||||
}
|
||||
|
||||
@@ -37,41 +41,95 @@ public class VpdPolicyController {
|
||||
@RequestParam(required = false) String schemaOwner,
|
||||
Model model
|
||||
) {
|
||||
populatePolicyModel(schemaOwner, model);
|
||||
populatePolicyModel(schemaOwner, true, model);
|
||||
return "vpd-filter-policies";
|
||||
}
|
||||
|
||||
private void populatePolicyModel(String schemaOwner, Model model) {
|
||||
/** Read-only operational view of the default dynamic permission filter. */
|
||||
@GetMapping("/vpd-filter-runtime")
|
||||
public String filterRuntime(Model model) {
|
||||
try {
|
||||
List<VpdPolicyView> policies = vpdPolicyService.findPolicies().stream()
|
||||
.filter(VpdPolicyView::permissionSystemDefault)
|
||||
.toList();
|
||||
model.addAttribute("policies", policies);
|
||||
if (!policies.isEmpty()) {
|
||||
VpdPolicyView filter = policies.get(0);
|
||||
model.addAttribute("source", vpdPolicyService.findFunctionSource(
|
||||
filter.functionOwner(), filter.packageName(), filter.functionName()));
|
||||
}
|
||||
} catch (DataAccessException exception) {
|
||||
RuntimeErrorMessage message = RuntimeErrorMessages.dataAccess(exception);
|
||||
model.addAttribute("runtimeError", message);
|
||||
model.addAttribute("policies", List.of());
|
||||
} catch (AppException exception) {
|
||||
model.addAttribute("errorMessage", exception.getMessage());
|
||||
model.addAttribute("policies", List.of());
|
||||
}
|
||||
return "vpd-filter-runtime";
|
||||
}
|
||||
|
||||
private void populatePolicyModel(String schemaOwner, boolean includeFilterEditor, Model model) {
|
||||
try {
|
||||
long started = System.nanoTime();
|
||||
String selectedSchemaOwner = schemaOwner == null ? "" : schemaOwner.trim().toUpperCase();
|
||||
List<com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyView> policies = vpdPolicyService.findPolicies();
|
||||
long policiesAt = System.nanoTime();
|
||||
Map<String, String> policyDescriptions = new LinkedHashMap<>();
|
||||
policies.forEach(policy -> policyDescriptions.put(
|
||||
policy.objectDisplayName() + "|" + policy.policyName(),
|
||||
vpdPolicyService.findPolicyDescription(policy.objectOwner(), policy.objectName(), policy.policyName())
|
||||
));
|
||||
if (!includeFilterEditor) {
|
||||
policyDescriptions.putAll(vpdPolicyService.findPolicyDescriptionMap());
|
||||
policies.forEach(policy -> policyDescriptions.put(
|
||||
policy.objectDisplayName() + "|" + policy.policyName(),
|
||||
policyDescriptions.getOrDefault(
|
||||
policy.objectDisplayName() + "|" + policy.policyName(),
|
||||
policy.objectDisplayName() + "에 요청마다 현재 권한체계의 행 접근 조건을 적용하는 "
|
||||
+ policy.policyName() + " policy입니다."
|
||||
)
|
||||
));
|
||||
}
|
||||
long policyDescriptionsAt = System.nanoTime();
|
||||
model.addAttribute("policies", policies);
|
||||
model.addAttribute("policyDescriptions", policyDescriptions);
|
||||
model.addAttribute("vpdTargets", vpdPolicyService.findVpdTargets(selectedSchemaOwner));
|
||||
model.addAttribute("vpdTargets", includeFilterEditor
|
||||
? List.of()
|
||||
: vpdPolicyService.findVpdTargets(selectedSchemaOwner));
|
||||
long targetsAt = System.nanoTime();
|
||||
model.addAttribute("selectedSchemaOwner", selectedSchemaOwner);
|
||||
var formOptions = vpdPolicyService.formOptions();
|
||||
long formOptionsAt = System.nanoTime();
|
||||
Map<String, String> filterDescriptions = new LinkedHashMap<>();
|
||||
formOptions.functions().forEach(function -> filterDescriptions.put(
|
||||
function.owner() + "|" + function.functionName(),
|
||||
vpdPolicyService.findFilterDescription(function.owner(), function.functionName())
|
||||
));
|
||||
filterDescriptions.putAll(vpdPolicyService.findFilterDescriptionMap());
|
||||
policies.forEach(policy -> filterDescriptions.putIfAbsent(
|
||||
policy.functionOwner() + "|" + policy.functionName(),
|
||||
vpdPolicyService.findFilterDescription(policy.functionOwner(), policy.functionName())
|
||||
defaultFilterDescription(policy.functionName())
|
||||
));
|
||||
if (includeFilterEditor) {
|
||||
formOptions.functions().forEach(function -> filterDescriptions.putIfAbsent(
|
||||
function.owner() + "|" + function.functionName(),
|
||||
defaultFilterDescription(function.functionName())
|
||||
));
|
||||
}
|
||||
long filterDescriptionsAt = System.nanoTime();
|
||||
Map<String, String> filterPredicates = new LinkedHashMap<>();
|
||||
formOptions.functions().forEach(function -> filterPredicates.put(
|
||||
function.owner() + "|" + function.functionName(),
|
||||
vpdPolicyService.findFilterPredicate(function.owner(), function.packageName(), function.functionName())
|
||||
));
|
||||
if (includeFilterEditor) {
|
||||
formOptions.functions().forEach(function -> filterPredicates.put(
|
||||
function.owner() + "|" + function.functionName(),
|
||||
vpdPolicyService.findFilterPredicate(function.owner(), function.packageName(), function.functionName())
|
||||
));
|
||||
}
|
||||
long predicatesAt = System.nanoTime();
|
||||
model.addAttribute("formOptions", formOptions);
|
||||
model.addAttribute("filterDescriptions", filterDescriptions);
|
||||
model.addAttribute("filterPredicates", filterPredicates);
|
||||
log.info("vpd page timings: editor={} policies={}ms policyDescriptions={}ms targets={}ms formOptions={}ms filterDescriptions={}ms predicates={}ms total={}ms",
|
||||
includeFilterEditor,
|
||||
elapsedMillis(started, policiesAt),
|
||||
elapsedMillis(policiesAt, policyDescriptionsAt),
|
||||
elapsedMillis(policyDescriptionsAt, targetsAt),
|
||||
elapsedMillis(targetsAt, formOptionsAt),
|
||||
elapsedMillis(formOptionsAt, filterDescriptionsAt),
|
||||
elapsedMillis(filterDescriptionsAt, predicatesAt),
|
||||
elapsedMillis(started, predicatesAt));
|
||||
} catch (DataAccessException exception) {
|
||||
RuntimeErrorMessage message = RuntimeErrorMessages.dataAccess(exception);
|
||||
model.addAttribute("runtimeError", message);
|
||||
@@ -94,6 +152,16 @@ public class VpdPolicyController {
|
||||
}
|
||||
}
|
||||
|
||||
private static String defaultFilterDescription(String functionName) {
|
||||
return "CB_AGENT_DOC_VPD_FILTER".equalsIgnoreCase(functionName)
|
||||
? "사용자·그룹·역할·TAG 권한을 동적으로 합쳐 VPD predicate를 반환합니다."
|
||||
: "이 Filter function이 반환하는 predicate로 조회 행을 제한합니다.";
|
||||
}
|
||||
|
||||
private static long elapsedMillis(long started, long finished) {
|
||||
return (finished - started) / 1_000_000;
|
||||
}
|
||||
|
||||
@PostMapping("/vpd-policies")
|
||||
public String createPolicy(
|
||||
@RequestParam String objectKey,
|
||||
|
||||
Reference in New Issue
Block a user