From d29c2a471be3c4fc46016378b946b75400569a77 Mon Sep 17 00:00:00 2001 From: "Dhaval.Rajpara" Date: Thu, 26 Oct 2023 02:23:18 -0700 Subject: [PATCH] RANGER-4010: updated react UI to support multiple resource-sets in policies Signed-off-by: Madhan Neethiraj --- .../react-webapp/src/components/Editable.jsx | 16 +- .../webapp/react-webapp/src/styles/style.css | 5 + .../react-webapp/src/utils/XAMessages.js | 4 +- .../webapp/react-webapp/src/utils/XAUtils.js | 28 +- .../AdminLogs/PolicyViewDetails.jsx | 179 ++++---- .../PolicyListing/AddUpdatePolicyForm.jsx | 430 +++++++++++++----- .../PolicyListing/PolicyConditionsComp.jsx | 2 +- .../src/views/PolicyListing/PolicyListing.jsx | 15 +- .../PolicyListing/PolicyPermissionItem.jsx | 106 +++-- .../src/views/Resources/ModalResourceComp.jsx | 1 + .../src/views/Resources/ResourceComp.jsx | 66 ++- .../views/Resources/ResourceSelectComp.jsx | 20 +- .../views/SecurityZone/SecurityZoneForm.jsx | 1 - .../ServiceManager/ServiceAuditFilter.jsx | 1 - 14 files changed, 571 insertions(+), 303 deletions(-) diff --git a/security-admin/src/main/webapp/react-webapp/src/components/Editable.jsx b/security-admin/src/main/webapp/react-webapp/src/components/Editable.jsx index eab4060d02..98495f6cc8 100644 --- a/security-admin/src/main/webapp/react-webapp/src/components/Editable.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/components/Editable.jsx @@ -57,7 +57,7 @@ const CheckboxComp = (props) => { setVal(val); }; - const handleAllChekced = (e) => { + const handleAllChecked = (e) => { let val = []; if (e.target.checked) { val = [...options]; @@ -92,7 +92,7 @@ const CheckboxComp = (props) => { checked={isAllChecked()} type="checkbox" label={selectAllLabel} - onChange={(e) => handleAllChekced(e)} + onChange={(e) => handleAllChecked(e)} /> )} @@ -126,7 +126,7 @@ const RadioBtnComp = (props) => { )); }; -const InputboxComp = (props) => { +const InputBoxComp = (props) => { const { value = "", valRef } = props; const [selectedInputVal, setInputVal] = useState(value); const handleChange = (e) => { @@ -160,7 +160,7 @@ const CustomCondition = (props) => { return ( <> {conditionDefVal?.length > 0 && - conditionDefVal.map((m) => { + conditionDefVal.map((m, index) => { let uiHintAttb = m.uiHint != undefined && m.uiHint != "" ? JSON.parse(m.uiHint) : ""; if (uiHintAttb != "") { @@ -249,7 +249,7 @@ const CustomCondition = (props) => { position="right" message={

- {RegexMessage.MESSAGE.policyconditioninfoicon} + {RegexMessage.MESSAGE.policyConditionInfoIcon}

} /> @@ -312,7 +312,7 @@ const CustomCondition = (props) => { ); }; -const innitialState = (props) => { +const initialState = (props) => { const { type, selectProps, value } = props; let val = value; if (!val) { @@ -369,7 +369,7 @@ const Editable = (props) => { state: false, errorMSG: "" }); - const [state, dispatch] = useReducer(reducer, props, innitialState); + const [state, dispatch] = useReducer(reducer, props, initialState); const { show, value, target } = state; let isListenerAttached = false; @@ -714,7 +714,7 @@ const Editable = (props) => { ) : type === TYPE_RADIO ? ( ) : type === TYPE_INPUT ? ( - + ) : type === TYPE_CUSTOM ? ( , ', \", `) for policy name.", userNameValidationMsg: ( <> @@ -49,7 +49,7 @@ export const RegexMessage = {

), - policyconditioninfoicon: + policyConditionInfoIcon: "1. JavaScript Condition Examples :\ country_code == 'USA', time_range >= 900 time_range <= 1800 etc.\ 2. Dragging bottom-right corner of javascript condition editor(Textarea) can resizable", 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 20dece45fe..93629855c4 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 @@ -19,7 +19,13 @@ import React, { useState } from "react"; import { getUserProfile } from "Utils/appState"; -import { UserRoles, PathAssociateWithModule, QueryParams } from "Utils/XAEnums"; +import { + UserRoles, + PathAssociateWithModule, + QueryParams, + RangerPolicyType, + ServiceType +} from "Utils/XAEnums"; import { filter, find, @@ -34,7 +40,8 @@ import { isUndefined, isNull, some, - has + has, + sortBy } from "lodash"; import { matchRoutes } from "react-router-dom"; import dateFormat from "dateformat"; @@ -43,7 +50,6 @@ import CustomBreadcrumb from "../views/CustomBreadcrumb"; import { CustomTooltip } from "../components/CommonComponents"; import InfiniteScroll from "react-infinite-scroll-component"; import { toast } from "react-toastify"; -import { RangerPolicyType, ServiceType } from "./XAEnums"; import { policyInfoMessage } from "./XAMessages"; import { fetchApi } from "Utils/fetchAPI"; @@ -1436,3 +1442,19 @@ export const policyConditionUpdatedJSON = (policyCond) => { }); return newPolicyConditionJSON; }; + +// Get resources with help of policy type + +export const getResourcesDefVal = (serviceDef, policyType) => { + let resources = []; + if (RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == policyType) { + resources = sortBy(serviceDef.dataMaskDef.resources, "itemId"); + } else if ( + RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == policyType + ) { + resources = sortBy(serviceDef.rowFilterDef.resources, "itemId"); + } else { + resources = sortBy(serviceDef.resources, "itemId"); + } + return resources; +}; diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyViewDetails.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyViewDetails.jsx index 7d18afbccf..aa541bf724 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyViewDetails.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyViewDetails.jsx @@ -23,8 +23,8 @@ import { Table, Badge, Row, Col } from "react-bootstrap"; import { RangerPolicyType, DefStatus } from "../../../utils/XAEnums"; import dateFormat from "dateformat"; import { toast } from "react-toastify"; -import { find, isEmpty, sortBy } from "lodash"; -import { serverError } from "../../../utils/XAUtils"; +import { find, isEmpty, map, sortBy } from "lodash"; +import { getResourcesDefVal, serverError } from "../../../utils/XAUtils"; import { ModalLoader } from "../../../components/CommonComponents"; import { getServiceDef } from "../../../utils/appState"; @@ -34,6 +34,7 @@ export function PolicyViewDetails(props) { const [serviceDef, setServiceDef] = useState({}); const { updateServices } = props; let { allServiceDefs } = getServiceDef(); + const isMultiResources = true; useEffect(() => { if (props.paramsData.isRevert) { @@ -42,7 +43,7 @@ export function PolicyViewDetails(props) { if (props.paramsData.isChangeVersion) { fetchByVersion(); } else { - fetchInitalData(); + fetchInitialData(); } } }, [ @@ -50,7 +51,7 @@ export function PolicyViewDetails(props) { ? props.paramsData.isRevert : props.paramsData.version || props.paramsData.policyVersion ]); - const fetchInitalData = async () => { + const fetchInitialData = async () => { await fetchByEventTime(); }; @@ -144,8 +145,70 @@ export function PolicyViewDetails(props) { createdBy, createTime, validitySchedules, - zoneName + zoneName, + additionalResources } = access; + let additionalResourcesVal = []; + if (isMultiResources) { + additionalResourcesVal = [resources, ...(additionalResources || [])]; + } + + const getPolicyResources = (policyType, resourceval) => { + var filterResources = []; + let serviceTypeData = serviceDef; + var resourceDef = getResourcesDefVal(serviceTypeData, policyType); + for (let key in resourceval) { + let filterResourcesVal = find(resourceDef, { name: key }); + let resource = {}; + resource.label = filterResourcesVal && filterResourcesVal.label; + resource.level = filterResourcesVal && filterResourcesVal.level; + resource.values = resourceval[key].values; + if (filterResourcesVal && filterResourcesVal.recursiveSupported) { + resource.Rec_Recursive = resourceval[key].isRecursive + ? DefStatus.RecursiveStatus.STATUS_RECURSIVE.label + : DefStatus.RecursiveStatus.STATUS_NONRECURSIVE.label; + } + if (filterResourcesVal && filterResourcesVal.excludesSupported) { + resource.Rec_Exc = resourceval[key].isExcludes + ? DefStatus.ExcludeStatus.STATUS_EXCLUDE.label + : DefStatus.ExcludeStatus.STATUS_INCLUDE.label; + } + filterResources.push(resource); + } + return ( + <> + {sortBy(filterResources, "level").map((obj) => ( + + {obj.label} + + + + {obj.values.map((val, index) => ( +
+ + {val} + +
+ ))} + + +
+ {obj.Rec_Exc} +
+ +
+ + {obj.Rec_Recursive} + +
+ +
+ + + ))} + + ); + }; const getPolicyDetails = () => { const getPolicyType = (policyTypeVal) => { @@ -207,78 +270,6 @@ export function PolicyViewDetails(props) { ); }; - const getPolicyResources = (policyType, resourceval) => { - var resourceDef; - var filterResources = []; - let serviceTypeData = serviceDef; - if (policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value) { - resourceDef = serviceTypeData && serviceTypeData.resources; - } - if (policyType == RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value) { - resourceDef = serviceTypeData && serviceTypeData.dataMaskDef.resources; - } - if (policyType == RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value) { - resourceDef = serviceTypeData && serviceTypeData.rowFilterDef.resources; - } - for (let key in resourceval) { - let filterResourcesVal = find(resourceDef, { name: key }); - let resource = {}; - resource.label = filterResourcesVal && filterResourcesVal.label; - resource.level = filterResourcesVal && filterResourcesVal.level; - resource.values = resourceval[key].values; - if (filterResourcesVal && filterResourcesVal.recursiveSupported) { - resource.Rec_Recursive = resourceval[key].isRecursive - ? DefStatus.RecursiveStatus.STATUS_RECURSIVE.label - : DefStatus.RecursiveStatus.STATUS_NONRECURSIVE.label; - } - if (filterResourcesVal && filterResourcesVal.excludesSupported) { - resource.Rec_Exc = resourceval[key].isExcludes - ? DefStatus.ExcludeStatus.STATUS_EXCLUDE.label - : DefStatus.ExcludeStatus.STATUS_INCLUDE.label; - } - filterResources.push(resource); - } - return ( - <> - {sortBy(filterResources, "level").map((obj) => ( - - {obj.label} - - - - {obj.values.map((val, index) => ( -
- - {val} - -
- ))} - - -
- - {obj.Rec_Exc} - -
- -
- - {obj.Rec_Recursive} - -
- -
- - - ))} - - ); - }; - return loader ? ( ) : ( @@ -323,7 +314,7 @@ export function PolicyViewDetails(props) { : "--"} - {getPolicyResources(policyType, resources)} + {!isMultiResources && getPolicyResources(policyType, resources)} Description {!isEmpty(description) ? description : "--"} @@ -547,7 +538,7 @@ export function PolicyViewDetails(props) { return tableRow; }; - const getPolicyConditions = (conditions, serviceDef, serviceType) => { + const getPolicyConditions = (conditions, serviceDef) => { let filterServiceDef = serviceDef; const getConditionLabel = (label) => { let filterLabel = ""; @@ -631,6 +622,7 @@ export function PolicyViewDetails(props) { ) ); }; + return loader ? ( ) : ( @@ -653,16 +645,41 @@ export function PolicyViewDetails(props) { {getPolicyDetails(serviceDef)} + {isMultiResources && ( + <> +

Policy Resource :

+ {additionalResourcesVal && + map(additionalResourcesVal, (resourcesVal, index) => ( + <> + + + + + + + {getPolicyResources(policyType, resourcesVal)} +
+ #{index + 1} +
+ + ))} + + )} {(policyType == RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value || RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value) && !isEmpty(validitySchedules) && getValidityPeriod(validitySchedules)} {policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value && ( - <>{getPolicyConditions(conditions, serviceDef, serviceType)} + <>{getPolicyConditions(conditions, serviceDef)} )} {policyType == RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value && serviceType == "tag" && ( - <>{getPolicyConditions(conditions, serviceDef, serviceType)} + <>{getPolicyConditions(conditions, serviceDef)} )} {policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value && ( 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 60cc1f2682..90595f1b89 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 @@ -37,12 +37,14 @@ import { find, isEmpty, pick, - isObject, isArray, isEqual, forIn, has, - maxBy + maxBy, + map, + isUndefined, + forEach } from "lodash"; import { toast } from "react-toastify"; import { Loader, scrollToError } from "Components/CommonComponents"; @@ -58,7 +60,8 @@ import moment from "moment"; import { InfoIcon, commonBreadcrumb, - isPolicyExpired + isPolicyExpired, + getResourcesDefVal } from "../../utils/XAUtils"; import { useAccordionToggle } from "react-bootstrap/AccordionToggle"; import AccordionContext from "react-bootstrap/AccordionContext"; @@ -67,12 +70,15 @@ import { RegexMessage } from "../../utils/XAMessages"; import { policyInfo } from "Utils/XAUtils"; import { BlockUi } from "../../components/CommonComponents"; import { getServiceDef } from "../../utils/appState"; +import { FieldArray } from "react-final-form-arrays"; const noneOptions = { label: "None", value: "none" }; +const isMultiResources = true; + const initialState = { loader: true, serviceDetails: null, @@ -81,7 +87,7 @@ const initialState = { formData: {} }; -const PromtDialog = (props) => { +const PromptDialog = (props) => { const { isDirtyField, isUnblock } = props; usePrompt("Are you sure you want to leave", isDirtyField && !isUnblock); return null; @@ -109,7 +115,7 @@ const Condition = ({ when, is, children }) => ( ); -export default function AddUpdatePolicyForm(props) { +export default function AddUpdatePolicyForm() { let { serviceId, policyType, policyId } = useParams(); const navigate = useNavigate(); const { state } = useLocation(); @@ -127,9 +133,11 @@ export default function AddUpdatePolicyForm(props) { const [showDelete, setShowDelete] = useState(false); const [blockUI, setBlockUI] = useState(false); const toastId = React.useRef(null); + const [changePolicyItemPermissions, setChangePolicyItemPermissions] = + useState(false); useEffect(() => { - fetchInitalData(); + fetchInitialData(); }, []); const showDeleteModal = () => { @@ -213,11 +221,11 @@ export default function AddUpdatePolicyForm(props) { })); }; - const fetchInitalData = async () => { + const fetchInitialData = async () => { let serviceData = await fetchServiceDetails(); - let serviceCompData = serviceDefs?.allServiceDefs?.find((servicedef) => { - return servicedef.name == serviceData.type; + let serviceCompData = serviceDefs?.allServiceDefs?.find((serviceDef) => { + return serviceDef.name == serviceData.type; }); if (serviceCompData) { let serviceDefPolicyType = 0; @@ -359,6 +367,20 @@ export default function AddUpdatePolicyForm(props) { serviceCompData ) : [{}]; + let serviceCompResourcesDetails = getResourcesDefVal( + serviceCompData, + data.policyType + ); + if (serviceCompResourcesDetails) { + forEach(serviceCompResourcesDetails, (val) => { + if ( + val.accessTypeRestrictions && + val.accessTypeRestrictions.length > 0 + ) { + setChangePolicyItemPermissions(true); + } + }); + } if (policyId) { data.policyName = policyData?.name; data.isEnabled = policyData?.isEnabled; @@ -370,51 +392,91 @@ export default function AddUpdatePolicyForm(props) { policyData?.policyLabels?.map((val) => { return { label: val, value: val }; }); - let serviceCompResourcesDetails; - if ( - RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == - policyData?.policyType - ) { - serviceCompResourcesDetails = serviceCompData?.dataMaskDef?.resources; - } else if ( - RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == - policyData?.policyType - ) { - serviceCompResourcesDetails = serviceCompData?.rowFilterDef?.resources; - } else { - serviceCompResourcesDetails = serviceCompData?.resources; - } if (policyData?.resources) { - let lastResourceLevel = []; - Object.entries(policyData?.resources).map(([key, value]) => { - let setResources = find(serviceCompResourcesDetails, ["name", key]); - data[`resourceName-${setResources?.level}`] = setResources; - data[`value-${setResources?.level}`] = value.values.map((m) => { - return { label: m, value: m }; + if (!isMultiResources) { + let lastResourceLevel = []; + Object.entries(policyData?.resources).map(([key, value]) => { + let setResources = find(serviceCompResourcesDetails, ["name", key]); + data[`resourceName-${setResources?.level}`] = setResources; + data[`value-${setResources?.level}`] = value.values.map((m) => { + return { label: m, value: m }; + }); + if (setResources?.excludesSupported) { + data[`isExcludesSupport-${setResources?.level}`] = + value.isExcludes == false; + } + if (setResources?.recursiveSupported) { + data[`isRecursiveSupport-${setResources?.level}`] = + value?.isRecursive; + } + lastResourceLevel.push({ + level: setResources.level, + name: setResources.name + }); }); - if (setResources?.excludesSupported) { - data[`isExcludesSupport-${setResources?.level}`] = - value.isExcludes == false; + lastResourceLevel = maxBy(lastResourceLevel, "level"); + let setLastResources = find(serviceCompResourcesDetails, [ + "parent", + lastResourceLevel.name + ]); + if (setLastResources && setLastResources?.isValidLeaf) { + data[`resourceName-${setLastResources.level}`] = { + label: "None", + value: "none" + }; } - if (setResources?.recursiveSupported) { - data[`isRecursiveSupport-${setResources?.level}`] = - value?.isRecursive; + } else { + if (policyData.additionalResources || policyData.resources) { + policyData.additionalResources = [ + policyData.resources, + ...(policyData.additionalResources || []) + ]; + data.additionalResources = []; + map(policyData.additionalResources, function (resourceObj) { + let lastResourceLevel = [], + additionalResourcesObj = {}; + Object.entries(resourceObj).map(([key, value]) => { + let setResources = find(serviceCompResourcesDetails, [ + "name", + key + ]); + additionalResourcesObj[`resourceName-${setResources?.level}`] = + setResources; + additionalResourcesObj[`value-${setResources?.level}`] = + value.values.map((m) => { + return { label: m, value: m }; + }); + if (setResources?.excludesSupported) { + additionalResourcesObj[ + `isExcludesSupport-${setResources?.level}` + ] = value.isExcludes == false; + } + if (setResources?.recursiveSupported) { + additionalResourcesObj[ + `isRecursiveSupport-${setResources?.level}` + ] = value?.isRecursive; + } + lastResourceLevel.push({ + level: setResources.level, + name: setResources.name + }); + }); + lastResourceLevel = maxBy(lastResourceLevel, "level"); + let setLastResources = find(serviceCompResourcesDetails, [ + "parent", + lastResourceLevel.name + ]); + if (setLastResources && setLastResources?.isValidLeaf) { + additionalResourcesObj[ + `resourceName-${setLastResources.level}` + ] = { + label: "None", + value: "none" + }; + } + data.additionalResources.push(additionalResourcesObj); + }); } - lastResourceLevel.push({ - level: setResources.level, - name: setResources.name - }); - }); - lastResourceLevel = maxBy(lastResourceLevel, "level"); - let setLastResources = find(serviceCompResourcesDetails, [ - "parent", - lastResourceLevel.name - ]); - if (setLastResources && setLastResources?.isValidLeaf) { - data[`resourceName-${setLastResources.level}`] = { - label: "None", - value: "none" - }; } } if (policyData?.validitySchedules) { @@ -439,7 +501,6 @@ export default function AddUpdatePolicyForm(props) { /* Policy condition */ if (policyData?.conditions?.length > 0) { data.conditions = {}; - for (let val of policyData.conditions) { let conditionObj = find( policyConditionUpdatedJSON(serviceCompData?.policyConditions), @@ -459,6 +520,9 @@ export default function AddUpdatePolicyForm(props) { } } } + if (isMultiResources && isUndefined(data.additionalResources)) { + data.additionalResources = [{}]; + } data.isDenyAllElse = policyData?.isDenyAllElse || false; return data; }; @@ -573,8 +637,8 @@ export default function AddUpdatePolicyForm(props) { } let tableList = []; let tagAccessType = groupBy(accessTypesObj, function (m) { - let tagval = m; - return tagval.substr(0, tagval.indexOf(":")); + let tagVal = m; + return tagVal.substr(0, tagVal.indexOf(":")); }); for (let tagObjData in tagAccessType) { tableList.push({ @@ -689,17 +753,10 @@ export default function AddUpdatePolicyForm(props) { data.service = serviceDetails.name; let serviceCompRes; if (values.policyType != null) { - if ( - values.policyType == RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value - ) - serviceCompRes = serviceCompDetails.dataMaskDef.resources; - if ( - values.policyType == - RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value - ) - serviceCompRes = serviceCompDetails.rowFilterDef.resources; - if (values.policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value) - serviceCompRes = serviceCompDetails.resources; + serviceCompRes = getResourcesDefVal( + serviceCompDetails, + values.policyType + ); } const grpResources = groupBy(serviceCompRes || [], "level"); let grpResourcesKeys = []; @@ -708,28 +765,80 @@ export default function AddUpdatePolicyForm(props) { } grpResourcesKeys = grpResourcesKeys.sort(); data.resources = {}; - for (const level of grpResourcesKeys) { - if ( - values[`resourceName-${level}`] && - values[`resourceName-${level}`].value !== noneOptions.value - ) { - let defObj = serviceCompRes.find(function (m) { - if (m.name == values[`resourceName-${level}`].name) { - return m; + if (!isMultiResources) { + for (const level of grpResourcesKeys) { + if ( + values[`resourceName-${level}`] && + values[`resourceName-${level}`].value !== noneOptions.value + ) { + let defObj = serviceCompRes.find(function (m) { + if (m.name == values[`resourceName-${level}`].name) { + return m; + } + }); + data.resources[values[`resourceName-${level}`].name] = { + values: isArray(values[`value-${level}`]) + ? values[`value-${level}`]?.map(({ value }) => value) + : [values[`value-${level}`].value] + }; + if (defObj?.excludesSupported) { + data.resources[values[`resourceName-${level}`].name]["isExcludes"] = + defObj.excludesSupported && + values[`isExcludesSupport-${level}`] == false; } - }); - data.resources[values[`resourceName-${level}`].name] = { - isExcludes: - defObj.excludesSupported && - values[`isExcludesSupport-${level}`] == false, - isRecursive: - defObj.recursiveSupported && - !(values[`isRecursiveSupport-${level}`] === false), - values: isArray(values[`value-${level}`]) - ? values[`value-${level}`]?.map(({ value }) => value) - : [values[`value-${level}`].value] - }; + if (defObj?.recursiveSupported) { + data.resources[values[`resourceName-${level}`].name][ + "isRecursive" + ] = + defObj.recursiveSupported && + !(values[`isRecursiveSupport-${level}`] === false); + } + } } + } else { + data["additionalResources"] = []; + map(values.additionalResources, (resourceValue) => { + let additionalResourcesObj = {}; + for (const level of grpResourcesKeys) { + if ( + resourceValue[`resourceName-${level}`] && + resourceValue[`resourceName-${level}`].value !== noneOptions.value + ) { + let defObj = serviceCompRes.find(function (m) { + if (m.name == resourceValue[`resourceName-${level}`].name) { + return m; + } + }); + + additionalResourcesObj[ + resourceValue[`resourceName-${level}`].name + ] = { + values: isArray(resourceValue[`value-${level}`]) + ? resourceValue[`value-${level}`]?.map(({ value }) => value) + : [resourceValue[`value-${level}`].value] + }; + if (defObj?.excludesSupported) { + additionalResourcesObj[ + resourceValue[`resourceName-${level}`].name + ]["isExcludes"] = + defObj.excludesSupported && + resourceValue[`isExcludesSupport-${level}`] == false; + } + if (defObj?.recursiveSupported) { + additionalResourcesObj[ + resourceValue[`resourceName-${level}`].name + ]["isRecursive"] = + defObj.recursiveSupported && + !(resourceValue[`isRecursiveSupport-${level}`] === false); + } + } + } + data["additionalResources"].push(additionalResourcesObj); + }); + } + if (data?.additionalResources?.length > 0) { + data.resources = data.additionalResources[0]; + data.additionalResources.shift(); } if (values?.validitySchedules) { data["validitySchedules"] = []; @@ -908,19 +1017,10 @@ export default function AddUpdatePolicyForm(props) { }; const resourceErrorCheck = (errors, values) => { - let serviceCompResourcesDetails; - if ( - RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == values.policyType - ) { - serviceCompResourcesDetails = serviceCompDetails.dataMaskDef.resources; - } else if ( - RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == values.policyType - ) { - serviceCompResourcesDetails = serviceCompDetails.rowFilterDef.resources; - } else { - serviceCompResourcesDetails = serviceCompDetails.resources; - } - + let serviceCompResourcesDetails = getResourcesDefVal( + serviceCompDetails, + values.policyType + ); const grpResources = groupBy(serviceCompResourcesDetails || [], "level"); let grpResourcesKeys = []; for (const resourceKey in grpResources) { @@ -928,8 +1028,14 @@ export default function AddUpdatePolicyForm(props) { } grpResourcesKeys = grpResourcesKeys.sort(); for (const key of grpResourcesKeys) { - if (errors[`value-${key}`] !== undefined) { - return true; + if (isMultiResources) { + if (errors?.additionalResources?.length > 0) { + return true; + } + } else { + if (errors[`value-${key}`] !== undefined) { + return true; + } } } }; @@ -1020,21 +1126,19 @@ export default function AddUpdatePolicyForm(props) { }} render={({ handleSubmit, - submitting, values, invalid, errors, dirty, form: { - mutators: { push: addPolicyItem, pop: removePolicyItem, move } + mutators: { push: addPolicyItem, pop: removePolicyItem } }, - form, dirtyFields, modified, initialValues }) => ( <> - )}
-

Policy Details

+

Policy Details :

@@ -1195,7 +1299,7 @@ export default function AddUpdatePolicyForm(props) { > { RegexMessage.MESSAGE - .policynameinfoiconmessage + .policyNameInfoIconMessage }

} @@ -1278,16 +1382,17 @@ export default function AddUpdatePolicyForm(props) { )} /> - + {!isMultiResources && ( + + )} { + (keyName) => { if ( values.conditions[keyName] != "" && values.conditions[keyName] != null @@ -1442,7 +1547,64 @@ export default function AddUpdatePolicyForm(props) { )}
- {/* ------------------------------------------------- */} + {/* --------------------- Multiple Resources ---------------------------- */} + {isMultiResources && ( + <> +
+

Resources :

+
+ <> + + {({ fields }) => + fields.map((name, index) => ( + + + + + {values.additionalResources.length > 1 && ( + + + + )} + + )) + } + +
+ +
+ + + )} + {/*----------------------- Policy Item --------------------------- */} {values.policyType == 0 ? (
@@ -1465,6 +1627,10 @@ export default function AddUpdatePolicyForm(props) { fetchUsersData={fetchUsersData} fetchGroupsData={fetchGroupsData} fetchRolesData={fetchRolesData} + changePolicyItemPermissions={ + changePolicyItemPermissions + } + isMultiResources={isMultiResources} />
{serviceCompDetails?.options @@ -1489,6 +1655,10 @@ export default function AddUpdatePolicyForm(props) { fetchUsersData={fetchUsersData} fetchGroupsData={fetchGroupsData} fetchRolesData={fetchRolesData} + changePolicyItemPermissions={ + changePolicyItemPermissions + } + isMultiResources={isMultiResources} />
@@ -1554,6 +1724,10 @@ export default function AddUpdatePolicyForm(props) { fetchUsersData={fetchUsersData} fetchGroupsData={fetchGroupsData} fetchRolesData={fetchRolesData} + changePolicyItemPermissions={ + changePolicyItemPermissions + } + isMultiResources={isMultiResources} />
@@ -1574,6 +1748,10 @@ export default function AddUpdatePolicyForm(props) { fetchUsersData={fetchUsersData} fetchGroupsData={fetchGroupsData} fetchRolesData={fetchRolesData} + changePolicyItemPermissions={ + changePolicyItemPermissions + } + isMultiResources={isMultiResources} /> @@ -1605,6 +1783,10 @@ export default function AddUpdatePolicyForm(props) { fetchUsersData={fetchUsersData} fetchGroupsData={fetchGroupsData} fetchRolesData={fetchRolesData} + changePolicyItemPermissions={ + changePolicyItemPermissions + } + isMultiResources={isMultiResources} /> @@ -1633,6 +1815,10 @@ export default function AddUpdatePolicyForm(props) { fetchUsersData={fetchUsersData} fetchGroupsData={fetchGroupsData} fetchRolesData={fetchRolesData} + changePolicyItemPermissions={ + changePolicyItemPermissions + } + isMultiResources={isMultiResources} /> @@ -1653,15 +1839,15 @@ export default function AddUpdatePolicyForm(props) { resourceErrorCheck(errors, values) ) { let selector = - document.getElementById("isError") || - document.getElementById(key) || - document.querySelector( + document?.getElementById("isError") || + document?.getElementById(key) || + document?.querySelector( `input[name=${key}]` ) || - document.querySelector( + document?.querySelector( `input[id=${key}]` ) || - document.querySelector( + document?.querySelector( `span[className="invalid-field"]` ); scrollToError(selector); diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx index 47240bce69..f9aaa3a405 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyConditionsComp.jsx @@ -169,7 +169,7 @@ export default function PolicyConditionsComp(props) {

{ RegexMessage.MESSAGE - .policyconditioninfoicon + .policyConditionInfoIcon }

} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListing.jsx index 6d6facb912..c1752c2527 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListing.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/PolicyListing.jsx @@ -57,11 +57,11 @@ import { isSystemAdmin, isKeyAdmin, isUser, - parseSearchFilter + parseSearchFilter, + getResourcesDefVal } from "../../utils/XAUtils"; import { alertMessage, - RangerPolicyType, ResourcesOverrideInfoMsg, ServerAttrName } from "../../utils/XAEnums"; @@ -668,15 +668,8 @@ function PolicyListing(props) { let resourceSearchOpt = []; let serverRsrcAttrName = []; let policySearchInfoMsg = []; - if (RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == policyType) { - resources = serviceDef.dataMaskDef?.resources || []; - } else if ( - RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == policyType - ) { - resources = serviceDef.rowFilterDef?.resources || []; - } else { - resources = serviceDef?.resources || []; - } + + resources = getResourcesDefVal(serviceDef, policyType); resourceSearchOpt = map(resources, function (resource) { return { 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 4c3f71befa..ab9b3ce88b 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,7 +23,17 @@ import { FieldArray } from "react-final-form-arrays"; import { Col } from "react-bootstrap"; import { Field } from "react-final-form"; import AsyncSelect from "react-select/async"; -import { find, groupBy, isEmpty, isArray } from "lodash"; +import { + find, + groupBy, + isEmpty, + isArray, + has, + map, + filter, + some, + isEqual +} from "lodash"; import { toast } from "react-toastify"; import Editable from "Components/Editable"; import { RangerPolicyType } from "Utils/XAEnums"; @@ -49,7 +59,9 @@ export default function PolicyPermissionItem(props) { fetchUsersData, fetchGroupsData, fetchRolesData, - formValues + formValues, + changePolicyItemPermissions, + isMultiResources } = props; const dragItem = useRef(); const dragOverItem = useRef(); @@ -104,38 +116,70 @@ export default function PolicyPermissionItem(props) { }, []); const getAccessTypeOptions = () => { - let srcOp = []; - for (let i = grpResourcesKeys.length - 1; i >= 0; i--) { - let selectedResource = `resourceName-${grpResourcesKeys[i]}`; - if ( - formValues[selectedResource] && - formValues[selectedResource].value !== noneOptions.value - ) { - if ( - RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == - formValues.policyType - ) { - srcOp = serviceCompDetails.dataMaskDef.accessTypes; - } else if ( - RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == - formValues.policyType - ) { - srcOp = serviceCompDetails.rowFilterDef.accessTypes; - } else { - srcOp = serviceCompDetails.accessTypes; - } - if (formValues[selectedResource].accessTypeRestrictions?.length > 0) { - let op = []; - for (const name of formValues[selectedResource] - .accessTypeRestrictions) { - let typeOp = find(srcOp, { name }); - if (typeOp) { - op.push(typeOp); + let srcOp = [], + multiplePermissionItem = []; + if ( + RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == formValues.policyType + ) { + srcOp = serviceCompDetails.dataMaskDef.accessTypes; + } else if ( + RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == + formValues.policyType + ) { + srcOp = serviceCompDetails.rowFilterDef.accessTypes; + } else { + srcOp = serviceCompDetails.accessTypes; + } + if (changePolicyItemPermissions) { + if (isMultiResources) { + map(formValues.additionalResources, (resourceObj) => { + for (let i = grpResourcesKeys.length - 1; i >= 0; i--) { + let selectedResource = `resourceName-${grpResourcesKeys[i]}`; + if ( + resourceObj[selectedResource] && + resourceObj[selectedResource].value !== noneOptions.value + ) { + if ( + resourceObj[selectedResource].accessTypeRestrictions?.length > 0 + ) { + let op = []; + for (const name of resourceObj[selectedResource] + .accessTypeRestrictions) { + let typeOp = find(srcOp, { name }); + if (typeOp) { + op.push(typeOp); + } + } + multiplePermissionItem = [...multiplePermissionItem, ...op]; + } + break; + } + } + }); + srcOp = [...new Set(multiplePermissionItem)]; + } else { + for (let i = grpResourcesKeys.length - 1; i >= 0; i--) { + let selectedResource = `resourceName-${grpResourcesKeys[i]}`; + if ( + formValues[selectedResource] && + formValues[selectedResource].value !== noneOptions.value + ) { + if ( + formValues[selectedResource].accessTypeRestrictions?.length > 0 + ) { + let op = []; + for (const name of formValues[selectedResource] + .accessTypeRestrictions) { + let typeOp = find(srcOp, { name }); + if (typeOp) { + op.push(typeOp); + } + } + srcOp = op; } + break; } - srcOp = op; } - break; } } return srcOp.map(({ label, name: value }) => ({ diff --git a/security-admin/src/main/webapp/react-webapp/src/views/Resources/ModalResourceComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/Resources/ModalResourceComp.jsx index 5c04ce3b8e..f6e559041d 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/Resources/ModalResourceComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/Resources/ModalResourceComp.jsx @@ -68,6 +68,7 @@ export default function ModalResourceComp(props) { serviceCompDetails={serviceCompDetails} formValues={values} policyType={0} + isMultiResources={false} /> )} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/Resources/ResourceComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/Resources/ResourceComp.jsx index 452f05ace6..0067e6ee99 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/Resources/ResourceComp.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/Resources/ResourceComp.jsx @@ -22,11 +22,11 @@ import { Form as FormB, Row, Col } from "react-bootstrap"; import { Field } from "react-final-form"; import Select from "react-select"; import BootstrapSwitchButton from "bootstrap-switch-button-react"; -import { filter, groupBy, some, sortBy } from "lodash"; +import { filter, groupBy, some } from "lodash"; import { toast } from "react-toastify"; import { udfResourceWarning } from "../../utils/XAMessages"; -import { RangerPolicyType } from "Utils/XAEnums"; import ResourceSelectComp from "./ResourceSelectComp"; +import { getResourcesDefVal } from "../../utils/XAUtils"; const noneOptions = { label: "None", @@ -39,20 +39,14 @@ export default function ResourceComp(props) { formValues, serviceDetails, policyType, - policyItem, - policyId + policyId, + name, + isMultiResources } = props; const [rsrcState, setLoader] = useState({ loader: false, resourceKey: -1 }); const toastId = useRef(null); - let resources = sortBy(serviceCompDetails.resources, "itemId"); - if (RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == policyType) { - resources = sortBy(serviceCompDetails.dataMaskDef.resources, "itemId"); - } else if ( - RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == policyType - ) { - resources = sortBy(serviceCompDetails.rowFilterDef.resources, "itemId"); - } + let resources = getResourcesDefVal(serviceCompDetails, policyType); useEffect(() => { if (rsrcState.loader) { @@ -139,14 +133,7 @@ export default function ResourceComp(props) { delete formValues[`isExcludesSupport-${levelKey}`]; delete formValues[`isRecursiveSupport-${levelKey}`]; } - if (policyItem) { - removedSeletedAccess(); - } delete formValues[`value-${grpResourcesKeys[index]}`]; - setLoader({ - loader: true, - resourceKey: grpResourcesKeys[index] - }); let CurrentSelectedResourcs = selectedVal.name; for (let j = index + 1; j < grpResourcesKeys.length; j++) { let level = grpResourcesKeys[j]; @@ -167,21 +154,10 @@ export default function ResourceComp(props) { } input.onChange(selectedVal); - }; - - const removedSeletedAccess = () => { - for (const name of [ - "policyItems", - "allowExceptions", - "denyPolicyItems", - "denyExceptions" - ]) { - for (const policyObj of formValues[name]) { - if (policyObj?.accesses) { - policyObj.accesses = []; - } - } - } + setLoader({ + loader: true, + resourceKey: grpResourcesKeys[index] + }); }; return grpResourcesKeys.map((levelKey, index) => { @@ -215,8 +191,12 @@ export default function ResourceComp(props) { + name={ + isMultiResources + ? `${name}.resourceName-${levelKey}` + : `resourceName-${levelKey}` + } + render={({ input }) => formValues[resourceKey] ? ( renderResourceSelect(levelKey, index) ? ( @@ -254,6 +234,8 @@ export default function ResourceComp(props) { formValues={formValues} grpResourcesKeys={grpResourcesKeys} serviceDetails={serviceDetails} + name={name} + isMultiResources={isMultiResources} /> @@ -265,7 +247,11 @@ export default function ResourceComp(props) { ( ( { + e.stopPropagation(); setOptions([]); fetchResourceLookup( "", diff --git a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx index 91d2a3758e..d97dcf0413 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/SecurityZone/SecurityZoneForm.jsx @@ -1365,7 +1365,6 @@ const SecurityZoneForm = () => { modelState={modelState} handleSave={handleSave} handleClose={handleClose} - policyItem={true} /> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceAuditFilter.jsx b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceAuditFilter.jsx index 7dff7457a6..ae05a1f2c6 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceAuditFilter.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceAuditFilter.jsx @@ -561,7 +561,6 @@ export default function ServiceAuditFilter(props) { handleSave={handleSave} modelState={modelState} handleClose={handleClose} - policyItem={false} /> );