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 {
