diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java b/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java index 70c51e7..9cd09b7 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/service/VpdPolicyService.java @@ -56,6 +56,45 @@ public class VpdPolicyService { ); } + @Transactional + public void saveFilterFunction(String functionOwnerValue, String functionNameValue, String filterPredicateValue) { + String currentUser = jdbcTemplate.queryForObject("SELECT USER FROM dual", String.class); + String functionOwner = functionOwnerValue == null || functionOwnerValue.isBlank() + ? currentUser + : requiredIdentifier(functionOwnerValue, "Function owner"); + if (currentUser == null || !currentUser.equalsIgnoreCase(functionOwner)) { + throw new AppException("Filter function 등록/수정은 현재 연결 사용자 스키마에만 가능합니다. 현재 사용자: " + + currentUser + ", Function owner: " + functionOwner); + } + String functionName = requiredIdentifier(functionNameValue, "Function name"); + String filterPredicate = filterPredicateValue == null ? "" : filterPredicateValue.trim(); + if (filterPredicate.isBlank()) { + throw new AppException("Filter predicate는 필수입니다."); + } + createFilterFunction(functionName, filterPredicate); + } + + @Transactional + public void replacePolicy(String oldObjectKey, String oldPolicyName, VpdPolicyCreateCommand command) { + String[] objectParts = oldObjectKey == null ? new String[0] : oldObjectKey.split("\\.", 2); + if (objectParts.length != 2) { + throw new AppException("수정할 Policy 대상 형식이 올바르지 않습니다: " + oldObjectKey); + } + String objectOwner = requiredIdentifier(objectParts[0], "Object owner"); + String objectName = requiredIdentifier(objectParts[1], "Object name"); + String policyName = requiredIdentifier(oldPolicyName, "Policy name"); + jdbcTemplate.update(""" + BEGIN + DBMS_RLS.DROP_POLICY( + object_schema => ?, + object_name => ?, + policy_name => ? + ); + END; + """, objectOwner, objectName, policyName); + createPolicy(command); + } + public VpdBulkApplyResult bulkApplySchema( String schemaOwner, boolean includeTables, diff --git a/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java b/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java index a776d6e..d111e64 100644 --- a/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java +++ b/src/main/java/com/cloudhandson/vpdbackoffice/web/VpdPolicyController.java @@ -86,6 +86,67 @@ public class VpdPolicyController { return "redirect:/vpd-filter-policies"; } + @PostMapping("/vpd-filter-policies/filters") + public String saveFilter( + @RequestParam(required = false) String functionOwner, + @RequestParam String functionName, + @RequestParam String filterPredicate, + RedirectAttributes redirectAttributes + ) { + try { + vpdPolicyService.saveFilterFunction(functionOwner, functionName, filterPredicate); + redirectAttributes.addFlashAttribute("successMessage", "Filter function을 저장했습니다: " + functionName); + } catch (AppException exception) { + redirectAttributes.addFlashAttribute("errorMessage", exception.getMessage()); + } catch (DataAccessException exception) { + RuntimeErrorMessage message = RuntimeErrorMessages.dataAccess(exception); + redirectAttributes.addFlashAttribute("errorMessage", message.message()); + } + return "redirect:/vpd-filter-policies"; + } + + @PostMapping("/vpd-filter-policies/replace") + public String replaceFilterPolicy( + @RequestParam String oldObjectKey, + @RequestParam String oldPolicyName, + @RequestParam String objectKey, + @RequestParam String policyName, + @RequestParam(required = false) String functionKey, + @RequestParam(required = false) String functionOwner, + @RequestParam(required = false) String functionName, + @RequestParam(defaultValue = "SELECT") List statementTypes, + @RequestParam(defaultValue = "false") boolean enabled, + @RequestParam(defaultValue = "false") boolean updateCheck, + @RequestParam(required = false) String filterPredicate, + RedirectAttributes redirectAttributes + ) { + try { + String[] objectParts = objectKey.split("\\.", 2); + if (objectParts.length != 2) { + throw new AppException("조회 대상 형식이 올바르지 않습니다: " + objectKey); + } + vpdPolicyService.replacePolicy(oldObjectKey, oldPolicyName, new VpdPolicyCreateCommand( + objectParts[0], + objectParts[1], + policyName, + functionKey, + functionOwner, + functionName, + String.join(",", statementTypes), + enabled, + updateCheck, + filterPredicate + )); + redirectAttributes.addFlashAttribute("successMessage", "Policy를 수정했습니다: " + policyName); + } catch (AppException exception) { + redirectAttributes.addFlashAttribute("errorMessage", exception.getMessage()); + } catch (DataAccessException exception) { + RuntimeErrorMessage message = RuntimeErrorMessages.dataAccess(exception); + redirectAttributes.addFlashAttribute("errorMessage", message.message()); + } + return "redirect:/vpd-filter-policies"; + } + private void createPolicyInternal( String objectKey, String policyName, diff --git a/src/main/resources/templates/vpd-filter-policies.html b/src/main/resources/templates/vpd-filter-policies.html index 589abea..6c916d4 100644 --- a/src/main/resources/templates/vpd-filter-policies.html +++ b/src/main/resources/templates/vpd-filter-policies.html @@ -18,9 +18,81 @@
-

Filter Policy 등록

+

Filter 등록/수정

적용 현황 보기
+
+ + + + +
+ + + + +
+ +
+ + + +
+ +
+
+

Filter 목록

+ 0 +
+
+ + + + + + + + + + + + + + + + + + +
FunctionType수정
ADMIN.FILTERFUNCTION +
+ + + + + +
+
등록된 VPD filter function 후보가 없습니다.
+
+
+ +
+
+

Policy 등록

+
+
+
+

Policy 목록/수정

+ 0 +
+
+ + + + + + + + + + + + + + + + + + + + + + +
ObjectPolicyFunctionStatus수정
ADMIN.TABLEPOLICYADMIN.FILTERYES +
+ + + + + + + + + +
+
등록된 VPD policy가 없습니다.
+
+
+

스키마 벌크 적용

diff --git a/src/main/resources/templates/vpd-policies.html b/src/main/resources/templates/vpd-policies.html index f5fa982..01cf633 100644 --- a/src/main/resources/templates/vpd-policies.html +++ b/src/main/resources/templates/vpd-policies.html @@ -6,7 +6,7 @@

VPD 설정

-

보호 객체에 Oracle VPD policy를 등록하고, policy function/filter predicate를 확인합니다.

+

보호 객체에 적용된 Oracle VPD policy와 policy function/filter predicate를 확인합니다.

@@ -18,204 +18,10 @@
-

Policy 등록

+

적용 현황

+ Filter Policy 관리
-
- - - - - - -
- Statement Types -
- -
-
-
- - -
-
- - -
- -
- - - - -
- -
-
- -
-
-

스키마 벌크 적용

-
-
- - -
- Object Types -
- - -
-
- - - -
- Statement Types -
- -
-
-
- - -
-
- - -
- -
- - - -
- -
+

이 화면은 현재 DB에 적용된 VPD policy와 policy function/filter 상세를 조회합니다. 등록과 벌크 적용은 Filter Policy 관리에서 수행합니다.

@@ -310,17 +116,5 @@
-