This is an automated email from the ASF dual-hosted git repository.

dhavaljrajpara pushed a commit to branch CDPQE-50726
in repository https://gitbox.apache.org/repos/asf/ranger.git

commit 3fbc1f3b3bddf3c027b8ab4bb051bc1160beef49
Author: Dhaval Rajpara <[email protected]>
AuthorDate: Sat Oct 31 23:42:10 2026 +0530

    RANGER-5860: Fallback to resource access-type restrictions when missing in 
constraint definition and handle empty parameters
---
 .../main/webapp/react-webapp/src/utils/XAUtils.js  | 95 ++++++++++++++++++----
 .../PolicyPermissionItemVertical.jsx               | 10 ++-
 .../views/PolicyListing/PolicyPermissionItem.jsx   |  7 +-
 3 files changed, 94 insertions(+), 18 deletions(-)

diff --git a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js 
b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
index 87a556430..0ca29858d 100644
--- a/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
+++ b/security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
@@ -1609,13 +1609,76 @@ export const getConstraintDefByName = (serviceDef, 
constraintName) => {
   return find(serviceDef.constraintDefs, { name: constraintName }) || null;
 };
 
-export const getAccessTypesForConstraintDef = (serviceDef, constraintDef) => {
+/**
+ * For constraint policy (type 4) — walk the deepest selected resource in a row
+ * and return its accessTypeRestrictions names (or null when none).
+ * Checks the form-value option first (it carries the property from 
ResourceSelectComp),
+ * then falls back to the service-def resource definition.
+ */
+export const getLeafAccessTypeRestrictions = (formValues, serviceCompDetails) 
=> {
+  if (!formValues || !serviceCompDetails) {
+    return null;
+  }
+  const grpResourcesKeys = getResourceLevelKeysSorted(serviceCompDetails);
+  const allResources = serviceCompDetails?.resources || [];
+
+  const findInRow = (row) => {
+    for (let i = grpResourcesKeys.length - 1; i >= 0; i--) {
+      const sel = row[`resourceName-${grpResourcesKeys[i]}`];
+      if (!sel || sel.value === "none") {
+        continue;
+      }
+      // from the react-select option (ResourceSelectComp attaches it)
+      if (sel.accessTypeRestrictions?.length) {
+        return sel.accessTypeRestrictions;
+      }
+      // fall back to service-def resource
+      const resDef = find(allResources, { name: sel.name ?? sel.value });
+      if (resDef?.accessTypeRestrictions?.length) {
+        return resDef.accessTypeRestrictions;
+      }
+      return null; // deepest leaf found, no restrictions
+    }
+    return null;
+  };
+
+  if (formValues.additionalResources?.length) {
+    for (const row of formValues.additionalResources) {
+      const r = findInRow(row);
+      if (r?.length) {
+        return r;
+      }
+    }
+  }
+  return findInRow(formValues);
+};
+
+/**
+ * Access types for a single constraint rule row.
+ * Priority:
+ *   1. constraintDef.accessTypes (non-empty) → use those
+ *   2. else → all service-def accessTypes
+ * Then narrow by the selected leaf resource's accessTypeRestrictions (same as
+ * access-policy behaviour).
+ */
+export const getAccessTypesForConstraintDef = (
+  serviceDef,
+  constraintDef,
+  leafRestrictions = null
+) => {
   const allAccessTypes = serviceDef?.accessTypes || [];
-  if (!constraintDef?.accessTypes?.length) {
-    return allAccessTypes;
+  let base;
+  if (constraintDef?.accessTypes?.length) {
+    const allowed = new Set(constraintDef.accessTypes);
+    base = filter(allAccessTypes, (item) => allowed.has(item.name));
+  } else {
+    base = allAccessTypes;
   }
-  const allowed = new Set(constraintDef.accessTypes);
-  return filter(allAccessTypes, (item) => allowed.has(item.name));
+  if (leafRestrictions?.length) {
+    const restrictionSet = new Set(leafRestrictions);
+    return filter(base, (item) => restrictionSet.has(item.name));
+  }
+  return base;
 };
 
 export const mapAccessTypesToSelectOptions = (accessTypes) => {
@@ -2049,12 +2112,15 @@ export const 
pruneConstraintPolicyItemsToMatchedResources = (
       selectedServiceComponentDef,
       constraintName
     );
+    const leafRestrictions = getLeafAccessTypeRestrictions(
+      formValues,
+      selectedServiceComponentDef
+    );
     const allowedAccessTypes = new Set(
-      (
-        getAccessTypesForConstraintDef(
-          selectedServiceComponentDef,
-          constraintDef
-        ) || []
+      getAccessTypesForConstraintDef(
+        selectedServiceComponentDef,
+        constraintDef,
+        leafRestrictions
       ).map((at) => at.name)
     );
 
@@ -2083,10 +2149,9 @@ export const buildConstraintInfoForApi = 
(constraintInfoForm) => {
     return null;
   }
 
-  const info = { constraintName };
+  const parameters = {};
   const rawParams = constraintInfoForm.parameters;
   if (rawParams && typeof rawParams === "object") {
-    const parameters = {};
     Object.entries(rawParams).forEach(([paramKey, paramVal]) => {
       if (paramVal === "" || paramVal == null) {
         return;
@@ -2096,11 +2161,9 @@ export const buildConstraintInfoForApi = 
(constraintInfoForm) => {
           ? paramVal.value
           : String(paramVal);
     });
-    if (!isEmpty(parameters)) {
-      info.parameters = parameters;
-    }
   }
-  return info;
+  // always include parameters (empty map when def has no parameters)
+  return { constraintName, parameters };
 };
 
 const legacyFormPrincipalName = (principal) => {
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx
index 66fa4d194..09d052d64 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/PolicyPermissionItemVertical.jsx
@@ -44,6 +44,7 @@ import {
   getConstraintNameFromField,
   getConstraintDefByName,
   getAccessTypesForConstraintDef,
+  getLeafAccessTypeRestrictions,
   mapAccessTypesToSelectOptions
 } from "Utils/XAUtils";
 import { CustomTooltip } from "Components/CommonComponents";
@@ -86,6 +87,12 @@ export default function PolicyPermissionItemVertical({
     getMatchedConstraint
   );
 
+  // For constraint policy: leaf resource accessTypeRestrictions (computed 
once, reused per row)
+  const leafRestrictions =
+    RangerPolicyType.RANGER_CONSTRAINT_POLICY_TYPE.value == 
formValues.policyType
+      ? getLeafAccessTypeRestrictions(formValues, serviceCompDetails)
+      : null;
+
   const constraintSelectOptions = getMatchedConstraint.map((constraint) => ({
     label: constraint.label || constraint.name,
     value: constraint.name
@@ -226,7 +233,8 @@ export default function PolicyPermissionItemVertical({
                 ? mapAccessTypesToSelectOptions(
                     getAccessTypesForConstraintDef(
                       serviceCompDetails,
-                      rowConstraintDef
+                      rowConstraintDef,
+                      leafRestrictions
                     )
                   )
                 : [];
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
index b50191b0c..7e9c36998 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyPermissionItem.jsx
@@ -49,6 +49,7 @@ import {
   getConstraintDefByName,
   getConstraintNameFromField,
   getAccessTypesForConstraintDef,
+  getLeafAccessTypeRestrictions,
   mapAccessTypesToSelectOptions
 } from "Utils/XAUtils";
 import {
@@ -202,7 +203,11 @@ export default function PolicyPermissionItem(props) {
         rowConstraintName
       );
       srcOp = rowConstraintName
-        ? getAccessTypesForConstraintDef(serviceCompDetails, rowDef)
+        ? getAccessTypesForConstraintDef(
+            serviceCompDetails,
+            rowDef,
+            getLeafAccessTypeRestrictions(formValues, serviceCompDetails)
+          )
         : [];
       return mapAccessTypesToSelectOptions(srcOp);
     } else {

Reply via email to