fix #477: list vpd target objects
This commit is contained in:
@@ -2,6 +2,7 @@ package com.cloudhandson.vpdbackoffice.config;
|
||||
|
||||
import com.cloudhandson.vpdbackoffice.service.PermissionService;
|
||||
import com.cloudhandson.vpdbackoffice.service.ProtectedObjectService;
|
||||
import com.cloudhandson.vpdbackoffice.service.VpdPolicyService;
|
||||
import java.sql.Connection;
|
||||
import javax.sql.DataSource;
|
||||
import org.slf4j.Logger;
|
||||
@@ -17,15 +18,18 @@ public class DbPoolWarmup {
|
||||
private final DataSource dataSource;
|
||||
private final ProtectedObjectService protectedObjectService;
|
||||
private final PermissionService permissionService;
|
||||
private final VpdPolicyService vpdPolicyService;
|
||||
|
||||
public DbPoolWarmup(
|
||||
DataSource dataSource,
|
||||
ProtectedObjectService protectedObjectService,
|
||||
PermissionService permissionService
|
||||
PermissionService permissionService,
|
||||
VpdPolicyService vpdPolicyService
|
||||
) {
|
||||
this.dataSource = dataSource;
|
||||
this.protectedObjectService = protectedObjectService;
|
||||
this.permissionService = permissionService;
|
||||
this.vpdPolicyService = vpdPolicyService;
|
||||
}
|
||||
|
||||
@EventListener(ApplicationReadyEvent.class)
|
||||
@@ -45,6 +49,8 @@ public class DbPoolWarmup {
|
||||
protectedObjectService.findDatabaseObjects();
|
||||
permissionService.findRoles();
|
||||
permissionService.findPermissionViews();
|
||||
vpdPolicyService.findVpdTargets();
|
||||
vpdPolicyService.formOptions();
|
||||
log.info("Backoffice DB catalog cache warmed up in {}ms", (System.nanoTime() - started) / 1_000_000);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
package com.cloudhandson.vpdbackoffice.domain.vpd;
|
||||
|
||||
public record VpdTargetView(
|
||||
String owner,
|
||||
String objectName,
|
||||
String objectType,
|
||||
String protectedYn,
|
||||
String ordsPath,
|
||||
int policyCount,
|
||||
String policyNames
|
||||
) {
|
||||
|
||||
public String objectDisplayName() {
|
||||
return owner + "." + objectName;
|
||||
}
|
||||
|
||||
public boolean protectedObject() {
|
||||
return "Y".equalsIgnoreCase(protectedYn);
|
||||
}
|
||||
|
||||
public boolean vpdApplied() {
|
||||
return policyCount > 0;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@ package com.cloudhandson.vpdbackoffice.mapper;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdFunctionOption;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdSchemaObjectOption;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdTargetView;
|
||||
import java.util.List;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
@@ -12,6 +13,8 @@ public interface VpdPolicyMapper {
|
||||
|
||||
List<VpdPolicyView> findPolicies();
|
||||
|
||||
List<VpdTargetView> findVpdTargets();
|
||||
|
||||
List<String> findPolicyNameOptions();
|
||||
|
||||
List<String> findSchemaOwnerOptions();
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyExplanation;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyFormOptions;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdPolicyView;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdSchemaObjectOption;
|
||||
import com.cloudhandson.vpdbackoffice.domain.vpd.VpdTargetView;
|
||||
import com.cloudhandson.vpdbackoffice.mapper.VpdPolicyMapper;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
@@ -21,10 +22,13 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
public class VpdPolicyService {
|
||||
|
||||
private static final Set<String> ALLOWED_STATEMENTS = Set.of("SELECT", "INSERT", "UPDATE", "DELETE", "INDEX");
|
||||
private static final long CATALOG_CACHE_MILLIS = 60_000L;
|
||||
|
||||
private final VpdPolicyMapper mapper;
|
||||
private final JdbcTemplate jdbcTemplate;
|
||||
private final OpenAiCompatibleClient aiClient;
|
||||
private volatile CacheEntry<List<VpdTargetView>> vpdTargetsCache;
|
||||
private volatile CacheEntry<VpdPolicyFormOptions> formOptionsCache;
|
||||
|
||||
public VpdPolicyService(VpdPolicyMapper mapper, JdbcTemplate jdbcTemplate, OpenAiCompatibleClient aiClient) {
|
||||
this.mapper = mapper;
|
||||
@@ -36,14 +40,30 @@ public class VpdPolicyService {
|
||||
return mapper.findPolicies();
|
||||
}
|
||||
|
||||
public List<VpdTargetView> findVpdTargets() {
|
||||
CacheEntry<List<VpdTargetView>> cached = vpdTargetsCache;
|
||||
if (cached != null && !cached.expired()) {
|
||||
return cached.value();
|
||||
}
|
||||
List<VpdTargetView> targets = List.copyOf(mapper.findVpdTargets());
|
||||
vpdTargetsCache = new CacheEntry<>(targets, System.currentTimeMillis() + CATALOG_CACHE_MILLIS);
|
||||
return targets;
|
||||
}
|
||||
|
||||
public VpdPolicyFormOptions formOptions() {
|
||||
return new VpdPolicyFormOptions(
|
||||
CacheEntry<VpdPolicyFormOptions> cached = formOptionsCache;
|
||||
if (cached != null && !cached.expired()) {
|
||||
return cached.value();
|
||||
}
|
||||
VpdPolicyFormOptions options = new VpdPolicyFormOptions(
|
||||
mapper.findPolicyNameOptions(),
|
||||
mapper.findSchemaOwnerOptions(),
|
||||
mapper.findOwnerOptions(),
|
||||
mapper.findFunctionOptions(),
|
||||
List.of("SELECT", "INSERT", "UPDATE", "DELETE", "INDEX")
|
||||
);
|
||||
formOptionsCache = new CacheEntry<>(options, System.currentTimeMillis() + CATALOG_CACHE_MILLIS);
|
||||
return options;
|
||||
}
|
||||
|
||||
public VpdPolicyFormOptions emptyFormOptions() {
|
||||
@@ -72,6 +92,7 @@ public class VpdPolicyService {
|
||||
throw new AppException("Filter predicate는 필수입니다.");
|
||||
}
|
||||
createFilterFunction(functionName, filterPredicate);
|
||||
clearCatalogCache();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@@ -93,6 +114,7 @@ public class VpdPolicyService {
|
||||
END;
|
||||
""", objectOwner, objectName, policyName);
|
||||
createPolicy(command);
|
||||
clearCatalogCache();
|
||||
}
|
||||
|
||||
public VpdBulkApplyResult bulkApplySchema(
|
||||
@@ -178,6 +200,7 @@ public class VpdPolicyService {
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
clearCatalogCache();
|
||||
return new VpdBulkApplyResult(targets.size(), created, skipped, failed);
|
||||
}
|
||||
|
||||
@@ -246,6 +269,12 @@ public class VpdPolicyService {
|
||||
command.enabled(),
|
||||
command.updateCheck()
|
||||
);
|
||||
clearCatalogCache();
|
||||
}
|
||||
|
||||
public void clearCatalogCache() {
|
||||
vpdTargetsCache = null;
|
||||
formOptionsCache = null;
|
||||
}
|
||||
|
||||
private void addPolicy(
|
||||
@@ -496,6 +525,13 @@ public class VpdPolicyService {
|
||||
return value.replace("'", "''");
|
||||
}
|
||||
|
||||
private record CacheEntry<T>(T value, long expiresAt) {
|
||||
|
||||
boolean expired() {
|
||||
return System.currentTimeMillis() > expiresAt;
|
||||
}
|
||||
}
|
||||
|
||||
private record FunctionRef(String owner, String packageName, String functionName) {
|
||||
}
|
||||
|
||||
|
||||
@@ -39,12 +39,14 @@ public class VpdPolicyController {
|
||||
private void populatePolicyModel(Model model) {
|
||||
try {
|
||||
model.addAttribute("policies", vpdPolicyService.findPolicies());
|
||||
model.addAttribute("vpdTargets", vpdPolicyService.findVpdTargets());
|
||||
model.addAttribute("objects", protectedObjectService.findEnabled());
|
||||
model.addAttribute("formOptions", vpdPolicyService.formOptions());
|
||||
} catch (DataAccessException exception) {
|
||||
RuntimeErrorMessage message = RuntimeErrorMessages.dataAccess(exception);
|
||||
model.addAttribute("runtimeError", message);
|
||||
model.addAttribute("policies", List.of());
|
||||
model.addAttribute("vpdTargets", List.of());
|
||||
model.addAttribute("objects", List.of());
|
||||
model.addAttribute("formOptions", vpdPolicyService.emptyFormOptions());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user