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

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

commit 907039d5c222b5ad942fb2b359872d1f1860d117
Author: Dhaval Rajpara <[email protected]>
AuthorDate: Wed Oct 28 19:51:13 2026 +0530

    RANGER-5852 : Added code for Contraint policy type in old polivy form
---
 .../main/webapp/react-webapp/src/utils/XAUtils.js  | 147 +++++++++++++++-
 .../views/PolicyListing/AddUpdatePolicyForm.jsx    | 194 ++++++++++++++++++---
 .../NewPolicyForm/CreateNewPolicyForm.jsx          |  33 +---
 .../ConstraintPolicyParameterFields.jsx            |  67 ++++++-
 .../NewPolicyForm/policyFormValidation.js          |   9 +
 .../views/PolicyListing/PolicyPermissionItem.jsx   | 156 +++++++++++++++--
 6 files changed, 530 insertions(+), 76 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 66d4c14d4..87a556430 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
@@ -923,6 +923,8 @@ export const showGroupsOrUsersOrRolesForPolicy = (
     ];
   } else if (policyType == "1") {
     itemList = ["dataMaskPolicyItems"];
+  } else if (policyType == "4") {
+    itemList = ["constraintPolicyItems"];
   } else {
     itemList = ["rowFilterPolicyItems"];
   }
@@ -2003,7 +2005,7 @@ export const pruneConstraintPolicyItemsToMatchedResources 
= (
 ) => {
   const formValues = form.getState().values;
   if (
-    formValues?.policyType !==
+    Number(formValues?.policyType) !==
     RangerPolicyType.RANGER_CONSTRAINT_POLICY_TYPE.value
   ) {
     return;
@@ -2060,15 +2062,152 @@ export const 
pruneConstraintPolicyItemsToMatchedResources = (
       continue;
     }
 
-    const prunedAccesses = item.accesses.filter(
-      (a) => a?.type && allowedAccessTypes.has(a.type)
-    );
+    const prunedAccesses = item.accesses.filter((a) => {
+      const accessType = a?.type ?? a?.value;
+      return accessType && allowedAccessTypes.has(accessType);
+    });
     if (prunedAccesses.length !== item.accesses.length) {
       form.change(`${attrName}[${i}].accesses`, prunedAccesses);
     }
   }
 };
 
+export const buildConstraintInfoForApi = (constraintInfoForm) => {
+  if (!constraintInfoForm) {
+    return null;
+  }
+  const constraintName = getConstraintNameFromField(
+    constraintInfoForm.constraintName
+  );
+  if (!constraintName) {
+    return null;
+  }
+
+  const info = { constraintName };
+  const rawParams = constraintInfoForm.parameters;
+  if (rawParams && typeof rawParams === "object") {
+    const parameters = {};
+    Object.entries(rawParams).forEach(([paramKey, paramVal]) => {
+      if (paramVal === "" || paramVal == null) {
+        return;
+      }
+      parameters[paramKey] =
+        typeof paramVal === "object" && paramVal.value != null
+          ? paramVal.value
+          : String(paramVal);
+    });
+    if (!isEmpty(parameters)) {
+      info.parameters = parameters;
+    }
+  }
+  return info;
+};
+
+const legacyFormPrincipalName = (principal) => {
+  if (typeof principal !== "object") {
+    return principal;
+  }
+  if (principal.value != null) {
+    return principal.value;
+  }
+  if (principal.name != null) {
+    return principal.name;
+  }
+  return principal;
+};
+
+/** Serialize constraintPolicyItems from legacy AddUpdatePolicyForm state. */
+export const serializeConstraintPolicyItemsForApi = (
+  formData,
+  serviceCompDetails
+) => {
+  const items = formData?.constraintPolicyItems;
+  if (!items || items.length === 0) {
+    return [];
+  }
+
+  const isTagService = serviceCompDetails?.name === "tag";
+  const policyResourceItem = [];
+
+  for (const key of items) {
+    if (isEmpty(key) || Object.entries(key).length === 0) {
+      continue;
+    }
+
+    const obj = {};
+
+    if (key?.accesses?.length > 0 && !isTagService) {
+      obj.accesses = key.accesses.map((access) => ({
+        type: access.type ?? access.value,
+        isAllowed: true
+      }));
+    } else if (
+      key?.accesses?.tableList?.length > 0 &&
+      isTagService
+    ) {
+      let accessesData = [];
+      for (const data in key.accesses.tableList) {
+        accessesData = [
+          ...accessesData,
+          ...key.accesses.tableList[data].permission
+        ];
+      }
+      obj.accesses = accessesData.map((value) => ({
+        type: value,
+        isAllowed: true
+      }));
+    }
+
+    if (key.users && key.users.length > 0) {
+      obj.users = key.users.map(legacyFormPrincipalName);
+    }
+    if (key.groups && key.groups.length > 0) {
+      obj.groups = key.groups.map(legacyFormPrincipalName);
+    }
+    if (key.roles && key.roles.length > 0) {
+      obj.roles = key.roles.map(legacyFormPrincipalName);
+    }
+
+    if (key?.conditions && !isEmpty(key.conditions)) {
+      obj.conditions = [];
+      Object.entries(key.conditions).forEach(
+        ([conditionKey, conditionValue]) => {
+          if (conditionValue !== "" && conditionValue != null) {
+            obj.conditions.push({
+              type: conditionKey,
+              values: isArray(conditionValue)
+                ? conditionValue.map((m) =>
+                    typeof m === "object" && m.value != null ? m.value : m
+                  )
+                : [conditionValue]
+            });
+          }
+        }
+      );
+    }
+
+    const constraintInfo = buildConstraintInfoForApi(key.constraintInfo);
+    if (constraintInfo) {
+      obj.constraintInfo = constraintInfo;
+    }
+
+    if (!isEmpty(obj)) {
+      policyResourceItem.push(obj);
+    }
+  }
+
+  return policyResourceItem;
+};
+
+export const getEmptyPolicyItemArraysForNonConstraintType = () => ({
+  policyItems: [],
+  allowExceptions: [],
+  denyPolicyItems: [],
+  denyExceptions: [],
+  dataMaskPolicyItems: [],
+  rowFilterPolicyItems: []
+});
+
 //CommonFunction to get display label for policy permission item
 export const getPolicyPermissionItemDisplayLbl = (
   serviceDef,
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
index 2c6f2a7b2..fae52503c 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/AddUpdatePolicyForm.jsx
@@ -74,8 +74,15 @@ import {
   getAllTimeZoneList,
   policyConditionUpdatedJSON,
   policyInfo,
-  getPolicyConditionDisplayLbl
+  getPolicyConditionDisplayLbl,
+  serializeConstraintPolicyItemsForApi,
+  pruneConstraintPolicyItemsToMatchedResources,
+  getEmptyPolicyItemArraysForNonConstraintType
 } from "Utils/XAUtils";
+import {
+  hasMissingConstraintFieldsOnPolicyItems,
+  validatePolicyItemsArray
+} from "./NewPolicyForm/policyFormValidation";
 import { useAccordionButton } from "react-bootstrap/AccordionButton";
 import AccordionContext from "react-bootstrap/AccordionContext";
 import usePrompt from "Hooks/usePrompt";
@@ -305,6 +312,16 @@ export default function AddUpdatePolicyForm() {
             serviceCompData
           )
         : [{}];
+    data.constraintPolicyItems =
+      policyId && policyData?.constraintPolicyItems?.length > 0
+        ? setPolicyItemVal(
+            policyData.constraintPolicyItems,
+            serviceCompData?.accessTypes,
+            null,
+            serviceCompData?.name,
+            serviceCompData
+          )
+        : [{}];
     let serviceCompResourcesDetails = getResourcesDefVal(
       serviceCompData,
       data.policyType
@@ -319,6 +336,12 @@ export default function AddUpdatePolicyForm() {
         }
       });
     }
+    if (
+      Number(data.policyType) ===
+      RangerPolicyType.RANGER_CONSTRAINT_POLICY_TYPE.value
+    ) {
+      setChangePolicyItemPermissions(true);
+    }
     if (policyId) {
       data.policyName = policyData?.name;
       data.isEnabled = policyData?.isEnabled;
@@ -532,6 +555,23 @@ export default function AddUpdatePolicyForm() {
             }
           );
         }
+        if (key?.constraintInfo?.constraintName) {
+          const constraintName =
+            typeof key.constraintInfo.constraintName === "object"
+              ? key.constraintInfo.constraintName.value
+              : key.constraintInfo.constraintName;
+          if (constraintName) {
+            obj.constraintInfo = { constraintName };
+            if (
+              key.constraintInfo.parameters &&
+              !isEmpty(key.constraintInfo.parameters)
+            ) {
+              obj.constraintInfo.parameters = {
+                ...key.constraintInfo.parameters
+              };
+            }
+          }
+        }
 
         if (
           !isEmpty(obj) &&
@@ -652,36 +692,83 @@ export default function AddUpdatePolicyForm() {
         }
       }
 
+      if (val?.constraintInfo?.constraintName) {
+        const cName = val.constraintInfo.constraintName;
+        const def = find(serviceData?.constraintDefs, { name: cName });
+        obj.constraintInfo = {
+          constraintName: {
+            label: def?.label || cName,
+            value: cName
+          },
+          parameters: { ...(val.constraintInfo.parameters || {}) }
+        };
+      }
+
       return obj;
     });
   };
 
-  const handleSubmit = async (values) => {
-    let data = {};
+  const handleSubmit = async (values, form) => {
+    const isConstraintPolicy =
+      Number(values.policyType) ===
+      RangerPolicyType.RANGER_CONSTRAINT_POLICY_TYPE.value;
 
-    data.allowExceptions = getPolicyItemsVal(values, "allowExceptions");
+    if (isConstraintPolicy && form) {
+      pruneConstraintPolicyItemsToMatchedResources(form, serviceCompDetails);
+      values = form.getState().values;
+    }
 
-    data.policyItems = getPolicyItemsVal(values, "policyItems");
-    if (values?.isDenyAllElse) {
-      data.denyPolicyItems = [];
-      data.denyExceptions = [];
+    if (hasMissingConstraintFieldsOnPolicyItems(values, serviceCompDetails)) {
+      toast.error(
+        "Please complete each constraint rule: constraint name, permissions, 
and required parameters.",
+        { toastId: "constraintPolicyItems" }
+      );
+      return;
+    }
+
+    let data = {};
+
+    if (isConstraintPolicy) {
+      Object.assign(data, getEmptyPolicyItemArraysForNonConstraintType());
+      data.constraintPolicyItems = serializeConstraintPolicyItemsForApi(
+        values,
+        serviceCompDetails
+      );
+      if (data.constraintPolicyItems.length === 0) {
+        toast.error("Please add at least one complete constraint rule.", {
+          toastId: "constraintPolicyItemsEmpty"
+        });
+        return;
+      }
+      data.isDenyAllElse = false;
     } else {
-      data.denyPolicyItems = getPolicyItemsVal(values, "denyPolicyItems");
-      data.denyExceptions = getPolicyItemsVal(values, "denyExceptions");
+      data.allowExceptions = getPolicyItemsVal(values, "allowExceptions");
+      data.policyItems = getPolicyItemsVal(values, "policyItems");
+      if (values?.isDenyAllElse) {
+        data.denyPolicyItems = [];
+        data.denyExceptions = [];
+      } else {
+        data.denyPolicyItems = getPolicyItemsVal(values, "denyPolicyItems");
+        data.denyExceptions = getPolicyItemsVal(values, "denyExceptions");
+      }
+      data.dataMaskPolicyItems = getPolicyItemsVal(
+        values,
+        "dataMaskPolicyItems"
+      );
+      data.rowFilterPolicyItems = getPolicyItemsVal(
+        values,
+        "rowFilterPolicyItems"
+      );
+      data.constraintPolicyItems = [];
     }
-    data.dataMaskPolicyItems = getPolicyItemsVal(values, 
"dataMaskPolicyItems");
-    data.rowFilterPolicyItems = getPolicyItemsVal(
-      values,
-      "rowFilterPolicyItems"
-    );
     data.description = values.description ?? "";
     data.isAuditEnabled = values.isAuditEnabled ?? true;
-    data.isDenyAllElse = values.isDenyAllElse;
+    data.isDenyAllElse = isConstraintPolicy ? false : values.isDenyAllElse;
     data.isEnabled = values.isEnabled ?? true;
     data.name = values.policyName;
     data.policyLabels = (values.policyLabel || [])?.map(({ value }) => value);
     data.policyPriority = values.policyPriority ? "1" : "0";
-    data.policyType = values.policyType;
+    data.policyType = Number(values.policyType);
     data.service = serviceDetails.name;
     let serviceCompRes;
     if (values.policyType != null) {
@@ -878,12 +965,15 @@ export default function AddUpdatePolicyForm() {
         setBlockUI(false);
         toast.dismiss(toastId.current);
         toastId.current = toast.success("Policy save successfully!!");
-        navigate(`/service/${serviceId}/policies/${policyType}`, {
-          state: {
-            showLastPage: true,
-            addPageData: tablePageData
+        navigate(
+          `/service/${serviceId}/policies/${Number(values.policyType ?? 
policyType)}`,
+          {
+            state: {
+              showLastPage: true,
+              addPageData: tablePageData
+            }
           }
-        });
+        );
       } catch (error) {
         setBlockUI(false);
         let errorMsg = `Failed to save policy form`;
@@ -963,9 +1053,22 @@ export default function AddUpdatePolicyForm() {
       }
     });
 
-    return errorField !== undefined && errorField?.accesses
-      ? toast.error(errorField?.accesses, { toastId: "error1" })
-      : toast.error(errorField?.delegateAdmin, { toastId: "error1" });
+    if (errorField === undefined) {
+      return null;
+    }
+    if (errorField?.accesses) {
+      return toast.error(errorField.accesses, { toastId: "error1" });
+    }
+    if (errorField?.constraintName) {
+      return toast.error(errorField.constraintName, { toastId: "error1" });
+    }
+    if (errorField?.parameters) {
+      return toast.error(errorField.parameters, { toastId: "error1" });
+    }
+    if (errorField?.users) {
+      return toast.error(errorField.users, { toastId: "error1" });
+    }
+    return toast.error(errorField?.delegateAdmin, { toastId: "error1" });
   };
 
   const resourceErrorCheck = (errors, values) => {
@@ -1012,6 +1115,15 @@ export default function AddUpdatePolicyForm() {
                   text: "Required"
                 };
               }
+              const policyTypeNum = Number(values.policyType);
+              Object.assign(
+                errors,
+                validatePolicyItemsArray(
+                  values,
+                  policyTypeNum,
+                  serviceCompDetails
+                )
+              );
 
               return errors;
             }}
@@ -1708,6 +1820,38 @@ export default function AddUpdatePolicyForm() {
                         </>
                       </Accordion>
                     </div>
+                  ) : values.policyType ==
+                    RangerPolicyType.RANGER_CONSTRAINT_POLICY_TYPE.value ? (
+                    <div>
+                      <Accordion defaultActiveKey="0">
+                        <>
+                          <p className="formHeader">
+                            Constraint Rules:
+                            <CustomToggle eventKey="0"></CustomToggle>
+                          </p>
+                          <Accordion.Collapse eventKey="0">
+                            <>
+                              <div className="wrap">
+                                <PolicyPermissionItem
+                                  serviceDetails={serviceDetails}
+                                  serviceCompDetails={serviceCompDetails}
+                                  formValues={values}
+                                  addPolicyItem={addPolicyItem}
+                                  attrName="constraintPolicyItems"
+                                  fetchUsersData={fetchUsersData}
+                                  fetchGroupsData={fetchGroupsData}
+                                  fetchRolesData={fetchRolesData}
+                                  changePolicyItemPermissions={
+                                    changePolicyItemPermissions
+                                  }
+                                  isMultiResources={isMultiResources}
+                                />
+                              </div>
+                            </>
+                          </Accordion.Collapse>
+                        </>
+                      </Accordion>
+                    </div>
                   ) : (
                     <div>
                       <div>
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/CreateNewPolicyForm.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/CreateNewPolicyForm.jsx
index e41c48cac..e8497b4ba 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/CreateNewPolicyForm.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/CreateNewPolicyForm.jsx
@@ -27,7 +27,7 @@ import {
   prunePolicyItemAccessesToAllowedTypes,
   pruneConstraintPolicyItemsToMatchedResources,
   policyConditionUpdatedJSON,
-  getConstraintNameFromField
+  buildConstraintInfoForApi
 } from "Utils/XAUtils";
 import {
   buildActionReqsMapFromConditionDef,
@@ -159,37 +159,6 @@ const CreateNewPolicyForm = () => {
     }
   };
 
-  const buildConstraintInfoForApi = (constraintInfoForm) => {
-    if (!constraintInfoForm) {
-      return null;
-    }
-    const constraintName = getConstraintNameFromField(
-      constraintInfoForm.constraintName
-    );
-    if (!constraintName) {
-      return null;
-    }
-
-    const info = { constraintName };
-    const rawParams = constraintInfoForm.parameters;
-    if (rawParams && typeof rawParams === "object") {
-      const parameters = {};
-      Object.entries(rawParams).forEach(([paramKey, paramVal]) => {
-        if (paramVal === "" || paramVal == null) {
-          return;
-        }
-        parameters[paramKey] =
-          typeof paramVal === "object" && paramVal.value != null
-            ? paramVal.value
-            : String(paramVal);
-      });
-      if (!isEmpty(parameters)) {
-        info.parameters = parameters;
-      }
-    }
-    return info;
-  };
-
   /** Constraint policy (type 4) — API shape for constraintPolicyItems */
   const getConstraintPolicyItemsVal = (formData) => {
     const items = formData?.constraintPolicyItems;
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx
index 26007f6c6..c2dbcb87b 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields.jsx
@@ -23,7 +23,9 @@ import { Row, Col, Form as FormB } from "react-bootstrap";
 import BootstrapSwitchButton from "bootstrap-switch-button-react";
 
 const required = (value) =>
-  value !== undefined && value !== null && value !== "" ? undefined : 
"Required";
+  value !== undefined && value !== null && value !== ""
+    ? undefined
+    : "Required";
 
 export const getInitialParameterValue = (param) => {
   if (param.defaultValue === undefined || param.defaultValue === null) {
@@ -71,7 +73,9 @@ const validateParameter = (param) => (value) => {
     if (Array.isArray(value)) {
       return value.length > 0 ? undefined : "Required";
     }
-    return value != null && String(value).trim() !== "" ? undefined : 
"Required";
+    return value != null && String(value).trim() !== ""
+      ? undefined
+      : "Required";
   }
   return required(value);
 };
@@ -119,7 +123,8 @@ const ParameterControl = ({ param, input, meta }) => {
           <BootstrapSwitchButton
             id={inputId}
             checked={
-              input.value === true || String(input.value).toLowerCase() === 
"true"
+              input.value === true ||
+              String(input.value).toLowerCase() === "true"
             }
             onChange={(checked) => input.onChange(checked)}
             onlabel="Yes"
@@ -203,7 +208,10 @@ const ParameterControl = ({ param, input, meta }) => {
 /**
  * Renders constraint definition parameters in the same row layout as 
Constraint Name.
  */
-const ConstraintPolicyParameterFields = ({ parameters = [], fieldNamePrefix }) 
=> {
+const ConstraintPolicyParameterFields = ({
+  parameters = [],
+  fieldNamePrefix
+}) => {
   if (!parameters.length) {
     return (
       <p className="text-muted mb-0">No parameters for this constraint.</p>
@@ -215,7 +223,10 @@ const ConstraintPolicyParameterFields = ({ parameters = 
[], fieldNamePrefix }) =
       {parameters.map((param) => (
         <Row key={param.name} className="mb-4">
           <Col className="column-1-fixed text-end">
-            <FormB.Label htmlFor={`${param.name}-constraint-param`} 
className="mb-0">
+            <FormB.Label
+              htmlFor={`${param.name}-constraint-param`}
+              className="mb-0"
+            >
               {param.label || param.name}
               {param.mandatory ? (
                 <span className="required-mark">*</span>
@@ -241,4 +252,50 @@ const ConstraintPolicyParameterFields = ({ parameters = 
[], fieldNamePrefix }) =
   );
 };
 
+/** Compact parameter fields for legacy PolicyPermissionItem table column. */
+export const ConstraintPolicyParameterTableCell = ({
+  parameters = [],
+  fieldNamePrefix,
+  constraintSelected,
+  selectFirstMessage = "Please select constraint name first"
+}) => {
+  if (!constraintSelected) {
+    return (
+      <span className="text-muted small editable-add-text">
+        {selectFirstMessage}
+      </span>
+    );
+  }
+  if (!parameters.length) {
+    return (
+      <span className="text-muted small editable-add-text">
+        No parameters for this constraint
+      </span>
+    );
+  }
+
+  return (
+    <div className="table-editable">
+      {parameters.map((param) => (
+        <div key={param.name} className="mb-2 text-start">
+          <FormB.Label className="small mb-1 d-block">
+            {param.label || param.name}
+            {param.mandatory ? (
+              <span className="required-mark">*</span>
+            ) : null}
+          </FormB.Label>
+          <Field
+            name={`${fieldNamePrefix}.${param.name}`}
+            validate={validateParameter(param)}
+          >
+            {({ input, meta }) => (
+              <ParameterControl param={param} input={input} meta={meta} />
+            )}
+          </Field>
+        </div>
+      ))}
+    </div>
+  );
+};
+
 export default ConstraintPolicyParameterFields;
diff --git 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/policyFormValidation.js
 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/policyFormValidation.js
index fd0cf1c72..15fd61341 100644
--- 
a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/policyFormValidation.js
+++ 
b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/NewPolicyForm/policyFormValidation.js
@@ -31,6 +31,15 @@ export const validatePolicyName = (policyName) => {
 };
 
 const hasPrincipals = (item) => {
+  if (isArray(item.users) && item.users.length > 0) {
+    return true;
+  }
+  if (isArray(item.groups) && item.groups.length > 0) {
+    return true;
+  }
+  if (isArray(item.roles) && item.roles.length > 0) {
+    return true;
+  }
   const usersObj = item.users || {};
   return (
     (usersObj.users || []).length > 0 ||
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 351925128..959621786 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
@@ -23,6 +23,7 @@ import { FieldArray } from "react-final-form-arrays";
 import { Col } from "react-bootstrap";
 import { Field, useForm } from "react-final-form";
 import AsyncSelect from "react-select/async";
+import Select from "react-select";
 import {
   find,
   isEmpty,
@@ -43,8 +44,17 @@ import {
   drop,
   dragOver,
   getPolicyConditionDisplayLbl,
-  safeJsonParse
+  safeJsonParse,
+  getMatchedConstraintDefs,
+  getConstraintDefByName,
+  getConstraintNameFromField,
+  getAccessTypesForConstraintDef,
+  mapAccessTypesToSelectOptions
 } from "Utils/XAUtils";
+import {
+  buildDefaultConstraintParameters,
+  ConstraintPolicyParameterTableCell
+} from 
"./NewPolicyForm/PolicyCreateStepperStepComp/ConstraintPolicyParameterFields";
 import {
   selectInputCustomStyles,
   ConfirmationClearIndicator
@@ -88,10 +98,30 @@ export default function PolicyPermissionItem(props) {
 
   const form = useForm();
 
+  const isConstraintPolicy =
+    RangerPolicyType.RANGER_CONSTRAINT_POLICY_TYPE.value ==
+    formValues?.policyType;
+
+  const matchedConstraintDefs = getMatchedConstraintDefs(
+    serviceCompDetails,
+    formValues
+  );
+  const constraintSelectOptions = matchedConstraintDefs.map((constraint) => ({
+    label: constraint.label || constraint.name,
+    value: constraint.name
+  }));
+  const constraintSelectFirstMsg = "Please select constraint name first";
+
   if (serviceCompDetails?.policyConditions?.length > 0) {
     permList.push("Rule Conditions");
   }
+  if (isConstraintPolicy) {
+    permList.push("Constraint Name");
+  }
   permList.push("Permissions");
+  if (isConstraintPolicy) {
+    permList.push("Parameters");
+  }
   if (
     RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value ==
       formValues?.policyType &&
@@ -137,7 +167,21 @@ export default function PolicyPermissionItem(props) {
     enableResourcePruneDefer: true
   });
 
-  const getAccessTypeOptions = () => {
+  const handleConstraintNameChange = (input, fieldName, option) => {
+    input.onChange(option || null);
+    form.change(`${fieldName}.accesses`, undefined);
+    if (!option?.value) {
+      form.change(`${fieldName}.constraintInfo.parameters`, undefined);
+      return;
+    }
+    const def = getConstraintDefByName(serviceCompDetails, option.value);
+    form.change(
+      `${fieldName}.constraintInfo.parameters`,
+      buildDefaultConstraintParameters(def?.parameters)
+    );
+  };
+
+  const getAccessTypeOptions = (rowIndex) => {
     let srcOp = [],
       multiplePermissionItem = [];
     if (
@@ -149,10 +193,22 @@ export default function PolicyPermissionItem(props) {
       formValues.policyType
     ) {
       srcOp = serviceCompDetails.rowFilterDef.accessTypes;
+    } else if (isConstraintPolicy) {
+      const rowConstraintName = getConstraintNameFromField(
+        formValues?.[attrName]?.[rowIndex]?.constraintInfo?.constraintName
+      );
+      const rowDef = getConstraintDefByName(
+        serviceCompDetails,
+        rowConstraintName
+      );
+      srcOp = rowConstraintName
+        ? getAccessTypesForConstraintDef(serviceCompDetails, rowDef)
+        : [];
+      return mapAccessTypesToSelectOptions(srcOp);
     } else {
       srcOp = serviceCompDetails.accessTypes;
     }
-    if (changePolicyItemPermissions) {
+    if (changePolicyItemPermissions && !isConstraintPolicy) {
       if (isMultiResources) {
         map(formValues.additionalResources, (resourceObj) => {
           for (let i = grpResourcesKeys.length - 1; i >= 0; i--) {
@@ -627,7 +683,91 @@ export default function PolicyPermissionItem(props) {
                             )
                           );
                         }
+                        if (colName == "Constraint Name") {
+                          const allowedNames = new Set(
+                            constraintSelectOptions.map((o) => o.value)
+                          );
+                          const rowConstraintName = getConstraintNameFromField(
+                            fields.value[index]?.constraintInfo?.constraintName
+                          );
+                          return (
+                            <td key={colName} className="align-middle">
+                              <Field
+                                name={`${name}.constraintInfo.constraintName`}
+                                render={({ input }) => {
+                                  if (
+                                    changePolicyItemPermissions &&
+                                    rowConstraintName &&
+                                    !allowedNames.has(rowConstraintName)
+                                  ) {
+                                    form.change(
+                                      `${name}.constraintInfo.constraintName`,
+                                      null
+                                    );
+                                    form.change(
+                                      `${name}.constraintInfo.parameters`,
+                                      undefined
+                                    );
+                                    form.change(`${name}.accesses`, undefined);
+                                  }
+                                  return (
+                                    <Select
+                                      inputId={`${name}-constraint-name`}
+                                      options={constraintSelectOptions}
+                                      value={input.value}
+                                      onChange={(option) =>
+                                        handleConstraintNameChange(
+                                          input,
+                                          name,
+                                          option
+                                        )
+                                      }
+                                      onBlur={input.onBlur}
+                                      placeholder="Select constraint"
+                                      isClearable
+                                      isDisabled={
+                                        constraintSelectOptions.length === 0
+                                      }
+                                      styles={selectInputCustomStyles}
+                                    />
+                                  );
+                                }}
+                              />
+                            </td>
+                          );
+                        }
+                        if (colName == "Parameters") {
+                          const rowConstraintName = getConstraintNameFromField(
+                            fields.value[index]?.constraintInfo?.constraintName
+                          );
+                          const rowConstraintDef = getConstraintDefByName(
+                            serviceCompDetails,
+                            rowConstraintName
+                          );
+                          return (
+                            <td key={colName} className="align-middle">
+                              <ConstraintPolicyParameterTableCell
+                                parameters={rowConstraintDef?.parameters || []}
+                                
fieldNamePrefix={`${name}.constraintInfo.parameters`}
+                                constraintSelected={Boolean(rowConstraintName)}
+                                selectFirstMessage={constraintSelectFirstMsg}
+                              />
+                            </td>
+                          );
+                        }
                         if (colName == "Permissions") {
+                          const rowConstraintName = getConstraintNameFromField(
+                            fields.value[index]?.constraintInfo?.constraintName
+                          );
+                          if (isConstraintPolicy && !rowConstraintName) {
+                            return (
+                              <td key={colName} className="align-middle">
+                                <span className="text-muted small 
editable-add-text">
+                                  {constraintSelectFirstMsg}
+                                </span>
+                              </td>
+                            );
+                          }
                           if (serviceCompDetails?.name == "tag") {
                             return (
                               <td key={colName} className="align-middle">
@@ -643,7 +783,7 @@ export default function PolicyPermissionItem(props) {
                                   render={({ input }) => (
                                     <div className="table-editable">
                                       <TagBasePermissionItem
-                                        options={getAccessTypeOptions()}
+                                        options={getAccessTypeOptions(index)}
                                         inputVal={input}
                                         formValues={formValues}
                                         dataMaskIndex={index}
@@ -656,7 +796,7 @@ export default function PolicyPermissionItem(props) {
                               </td>
                             );
                           } else {
-                            let accessTypeOptions = getAccessTypeOptions();
+                            let accessTypeOptions = 
getAccessTypeOptions(index);
                             return (
                               <td key={colName} className="align-middle">
                                 <Field
@@ -678,11 +818,7 @@ export default function PolicyPermissionItem(props) {
                                     ) {
                                       let accTypeVal = filter(
                                         formValues[attrName][index].accesses,
-                                        (m) => {
-                                          if (some(accessTypeOptions, m)) {
-                                            return m;
-                                          }
-                                        }
+                                        (m) => some(accessTypeOptions, m)
                                       );
                                       if (!isEqual(input.value, accTypeVal)) {
                                         input.onChange(accTypeVal);

Reply via email to