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);
