diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-abfs.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-abfs.json index 7dcf388958..879df6b9fa 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-abfs.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-abfs.json @@ -118,7 +118,8 @@ "name": "ip-range", "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerIpMatcher", "label": "IP Address Range", - "description": "IP Address Range" + "description": "IP Address Range", + "uiHint" : "{ \"isMultiValue\":true }" } ] } \ No newline at end of file diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-kafka.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-kafka.json index 2f511eff52..b169c6ba93 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-kafka.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-kafka.json @@ -239,9 +239,9 @@ }, "validationRegEx":"", "validationMessage":"", - "uiHint":"", "label":"IP Address Range", - "description":"IP Address Range" + "description":"IP Address Range", + "uiHint" : "{ \"isMultiValue\":true }" } ] } diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-knox.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-knox.json index 410b9ef58c..ee44687b4e 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-knox.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-knox.json @@ -135,9 +135,9 @@ "evaluatorOptions": { }, "validationRegEx":"", "validationMessage": "", - "uiHint":"", "label": "IP Address Range", - "description": "IP Address Range" + "description": "IP Address Range", + "uiHint" : "{ \"isMultiValue\":true }" } ] } diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-ozone.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-ozone.json index 4b899736bf..13915130c4 100755 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-ozone.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-ozone.json @@ -254,9 +254,9 @@ "evaluatorOptions": { }, "validationRegEx":"", "validationMessage": "", - "uiHint":"", "label": "IP Address Range", - "description": "IP Address Range" + "description": "IP Address Range", + "uiHint" : "{ \"isMultiValue\":true }" } ] diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-schema-registry.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-schema-registry.json index 987a50fc54..bdebf406db 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-schema-registry.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-schema-registry.json @@ -264,9 +264,9 @@ }, "validationRegEx":"", "validationMessage":"", - "uiHint":"", "label":"IP Address Range", - "description":"IP Address Range" + "description":"IP Address Range", + "uiHint" : "{ \"isMultiValue\":true }" } ] diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-solr.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-solr.json index de33998457..50545f7449 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-solr.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-solr.json @@ -188,9 +188,9 @@ }, "validationRegEx":"", "validationMessage":"", - "uiHint":"", "label":"IP Address Range", - "description":"IP Address Range" + "description":"IP Address Range", + "uiHint" : "{ \"isMultiValue\":true }" } ] diff --git a/agents-common/src/main/resources/service-defs/ranger-servicedef-tag.json b/agents-common/src/main/resources/service-defs/ranger-servicedef-tag.json index 7cb523075f..add29feed4 100644 --- a/agents-common/src/main/resources/service-defs/ranger-servicedef-tag.json +++ b/agents-common/src/main/resources/service-defs/ranger-servicedef-tag.json @@ -88,7 +88,8 @@ "evaluator": "org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator", "evaluatorOptions" : {"engineName":"JavaScript", "ui.isMultiline":"true"}, "label":"Enter boolean expression", - "description": "Boolean expression" + "description": "Boolean expression", + "uiHint" : "{ \"isMultiline\":true }" } ] } 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 7dd32ebaa5..34eb8c5fad 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 @@ -17,7 +17,13 @@ * under the License. */ -import React, { useEffect, useReducer, useRef, useState, useCallback } from "react"; +import React, { + useEffect, + useReducer, + useRef, + useState, + useCallback +} from "react"; import { OverlayTrigger, Popover, @@ -27,13 +33,14 @@ import { Col, Badge } from "react-bootstrap"; -import { findIndex, isArray } from "lodash"; +import { find, findIndex, isArray, isEmpty, map } from "lodash"; import { isObject } from "Utils/XAUtils"; import CreatableSelect from "react-select/creatable"; import Select from "react-select"; import { InfoIcon } from "../utils/XAUtils"; import { RegexMessage } from "../utils/XAMessages"; +const esprima = require("esprima"); const TYPE_SELECT = "select"; const TYPE_CHECKBOX = "checkbox"; const TYPE_INPUT = "input"; @@ -75,7 +82,7 @@ const CheckboxComp = (props) => { return ( <> - {options.map((obj) => ( + {options.map((obj, index) => ( { ); }; -const CreatableSelectNew = (props) => { - const { value, valRef, conditionDefVal, selectProps } = props; - const [selectedInputVal, setSelectVal] = useState(value); - const handleChange = (e) => { - valRef.current = e; - setSelectVal(e); - }; - - return ( - <> - - {conditionDefVal.label}: - ({ label: obj, value: obj })) - : selectedInputVal - } - onChange={(e) => handleChange(e)} - placeholder="enter expression" - width="500px" - /> - - - ); -}; - const CustomCondition = (props) => { - const { value, valRef, conditionDefVal, selectProps } = props; - const accessedOpt = [ - { value: "yes", label: "Yes" }, - { value: "no", label: "No" } - ]; - const [selectedCondVal, setCondSelect] = useState( - value?.["accessed-after-expiry"] || value - ); - const [selectedJSCondVal, setJSCondVal] = useState( - value?.expression || value - ); + const { value, valRef, conditionDefVal, selectProps, validExpression } = + props; const tagAccessData = (val, key) => { if (!isObject(valRef.current)) { valRef.current = {}; } valRef.current[key] = val; }; - const selectHandleChange = (e, name) => { - setCondSelect(e); - tagAccessData(e?.value || null, name); - }; - const textAreaHandleChange = (e, name) => { - setJSCondVal(e.target.value); - tagAccessData(e.target.value, name); - }; - const accessedVal = (val) => { - let value = null; - if (val) { - let opObj = accessedOpt.filter((m) => { - if (m.value == val) { - return m; - } - }); - if (opObj) { - value = opObj; - } - } - return value; - }; - const expressionVal = (val) => { - let value = null; - if(val?.expression !== undefined){ - return value = val.expression; - } - if(val != "" && typeof(val) != "object"){ - return value = val - } - return value; - }; + return ( <> {conditionDefVal?.length > 0 && conditionDefVal.map((m, index) => { - if (m.name == "accessed-after-expiry") { - return ( - - {m.label}: - selectHandleChange(e, m.name)} + value={ + selectedCondVal?.value + ? accessedVal(selectedCondVal.value) + : accessedVal(selectedCondVal) + } + isMulti={true} + isClearable={false} + /> + + + ); + } + if (uiHintAttb?.isMultiline) { + const [selectedJSCondVal, setJSCondVal] = useState( + value?.[m.name] || value + ); + const expressionVal = (val) => { + let value = null; + if (val != "" && typeof val != "object") { + valRef.current[m.name] = val; + return (value = val); + } + return value !== null ? value : ""; + }; + const textAreaHandleChange = (e, name) => { + setJSCondVal(e.target.value); + tagAccessData(e.target.value, name); + }; + return ( +
+ + + + {m.label}: + + {RegexMessage.MESSAGE.policyconditioninfoicon} +

+ } + /> + +
+ + + textAreaHandleChange(e, m.name)} + isInvalid={validExpression.state} + /> + {validExpression.state && ( +
+ {validExpression.errorMSG} +
+ )} + +
+
+
+ ); + } + if (uiHintAttb?.isMultiValue) { + const [selectedInputVal, setSelectVal] = useState( + value?.[m.name] || [] + ); + const handleChange = (e, name) => { + setSelectVal(e); + tagAccessData(e, name); + }; + return ( +
+ + {m.label}: + ({ label: obj, value: obj })) + : selectedInputVal + } + onChange={(e) => handleChange(e, m.name)} + placeholder="enter expression" + width="500px" + isClearable={false} + /> + +
+ ); + } } })} @@ -339,35 +377,75 @@ const Editable = (props) => { const initialLoad = useRef(true); const popoverRef = useRef(null); const selectValRef = useRef(null); + const [validExpression, setValidated] = useState({ + state: false, + errorMSG: "" + }); const [state, dispatch] = useReducer(reducer, props, innitialState); const { show, value, target } = state; let isListenerAttached = false; - + const handleClickOutside = (e) => { - if (document.getElementById("popover-basic")?.contains(e?.target) == false) { - dispatch({ - type: "SET_POPOVER", - show: false, - target:null - }); - } - e?.stopPropagation() + if ( + document.getElementById("popover-basic")?.contains(e?.target) == false + ) { + dispatch({ + type: "SET_POPOVER", + show: false, + target: null + }); + } + e?.stopPropagation(); }; - + useEffect(() => { - if(!isListenerAttached){ - document?.addEventListener('mousedown', handleClickOutside); + if (!isListenerAttached) { + document?.addEventListener("mousedown", handleClickOutside); isListenerAttached = true; return; - } - return () => { - document?.removeEventListener('mousedown', handleClickOutside); + } + return () => { + document?.removeEventListener("mousedown", handleClickOutside); }; }, []); const displayValue = () => { let val = "--"; const selectVal = value; + const policyConditionDisplayValue = () => { + let ipRangVal, uiHintVal; + if (selectVal) { + return _.sortBy(Object.keys(selectVal)).map((property, index) => { + let conditionObj = find(conditionDefVal, function (m) { + if (m.name == property) { + return m; + } + }); + if (conditionObj?.uiHint && conditionObj?.uiHint != "") { + uiHintVal = JSON.parse(conditionObj.uiHint); + } + if (isArray(selectVal[property])) { + ipRangVal = selectVal[property] + ?.map(function (m) { + return m.value; + }) + .join(", "); + } + return ( +
+ {`${conditionObj.label}: ${ + isArray(selectVal[property]) ? ipRangVal : selectVal[property] + }`} +
+ ); + }); + } + }; if (displayFormat) { val = displayFormat(selectVal); } else { @@ -377,10 +455,10 @@ const Editable = (props) => { servicedefName == "knox" && !isArray(selectVal) ? selectVal["ip-range"] : selectVal - .map(function (m) { - return m.value; - }) - .join(", "); + .map(function (m) { + return m.value; + }) + .join(", "); val = (
{ selectVal && selectVal?.length > 0 ? ( <> - {selectVal.map((op, index) => ( + {selectVal.map((op, index) => (
- {op.label} + {op.label}
- ))} + ))}
- + ) : (
@@ -458,20 +536,21 @@ const Editable = (props) => { } else if (type === TYPE_INPUT) { val = selectVal && selectVal !== "" ? ( - <> - + <> +
- {selectVal} + {selectVal}
-
- - +
+ + ) : (
Add Row Filter @@ -488,12 +567,12 @@ const Editable = (props) => { } else if (type === TYPE_RADIO) { val = selectVal && selectVal?.label ? ( - <> - + <> +
- {selectVal.label} + {selectVal.label}
-
+
- + ) : (
Select Masking Option @@ -517,16 +596,15 @@ const Editable = (props) => {
); } else if (type === TYPE_CUSTOM) { - if (selectVal?.["accessed-after-expiry"] || selectVal?.expression) { + for (const key in selectVal) { + if (selectVal[key] == null || selectVal[key] == "") { + delete selectVal[key]; + } + } + if (Object.keys(selectVal).length != 0) { val = (
- {(selectVal?.["accessed-after-expiry"] !== undefined && selectVal?.["accessed-after-expiry"] !== null) && -
- {`Accessed after expiry_date (yes/no) : ${selectVal?.["accessed-after-expiry"]}`} -
} - {(selectVal?.expression !== undefined && selectVal?.expression !== "") && -
{`Boolean expression : ${selectVal?.expression}`} -
} + {policyConditionDisplayValue()}