diff --git a/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx b/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx index 053ced0e21..52d84ca558 100644 --- a/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/components/CommonComponents.jsx @@ -20,10 +20,18 @@ import { isEmpty, isObject, lastIndexOf } from "lodash"; import moment from "moment-timezone"; import React, { Component, useEffect, useMemo, useState } from "react"; -import { Alert, Badge, Button, OverlayTrigger, Popover } from "react-bootstrap"; +import { + Alert, + Badge, + Button, + OverlayTrigger, + Popover, + Modal +} from "react-bootstrap"; import { Field } from "react-final-form"; import { useLocation } from "react-router-dom"; import blockLoading from "Images/blockLoading.gif"; +import { components as selectComponents } from "react-select"; export const Loader = () => { return ( @@ -87,12 +95,12 @@ export class MoreLess extends Component { return ( <>
- {this?.state?.data?.map((key) => { + {this?.state?.data?.map((key, index) => { return ( {key} @@ -577,3 +585,57 @@ export const trimInputValue = (e, input) => { } input.onBlur(e); // Always call onBlur to trigger validation }; + +export const ConfirmationClearIndicator = (props) => { + const [show, setShow] = useState(false); + + const message = `Are you sure you want to remove all selected ${props?.selectProps?.clearConfirmMessage} from this field?`; + + const open = (e) => { + e.preventDefault(); + e.stopPropagation(); + setShow(true); + }; + + const onNo = (e) => { + e.stopPropagation(); + setShow(false); + }; + + const onYes = (e) => { + e.stopPropagation(); + props.clearValue(); // clears all selected values (global clear) + props?.selectProps?.onClearConfirmed?.(); + setShow(false); + }; + + // Remove react-select's default inner event handlers so clicks only on our icon trigger the modal + const { innerProps = {}, ...rest } = props; + const { onMouseDown, ...cleanInnerProps } = innerProps; + + return ( + <> + + + + + + + setShow(false)}> + {message} + + + + + + + ); +}; 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 c5754ac958..a7de99eb1a 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 @@ -387,7 +387,8 @@ const Editable = (props) => { options = [], conditionDefVal, servicedefName, - isGDS + isGDS, + popOverheader } = props; const initialLoad = useRef(true); @@ -451,7 +452,9 @@ const Editable = (props) => {
{`${conditionObj.label}: ${ @@ -502,7 +505,6 @@ const Editable = (props) => { variant="outline-dark" size="sm" type="button" - s > @@ -514,7 +516,7 @@ const Editable = (props) => { selectVal && selectVal?.length > 0 ? ( <> - {selectVal.map((op, index) => ( + {sortBy(selectVal, "label").map((op, index) => (
{op.label}
@@ -729,9 +731,7 @@ const Editable = (props) => { type === TYPE_CHECKBOX && "popover-maxHeight popover-minHeight" }`} > - - {type === TYPE_CHECKBOX ? "Select" : "Enter"} - + {popOverheader} {type === TYPE_CHECKBOX ? ( ), - 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", + policyConditionInfoIcon:( + <> + + 1. Boolean expression Examples: +
+ country_code == 'USA', time_range >= 900 time_range <= 1800 etc. +
+ 2. The condition editor (textarea) can be resized by dragging its bottom-right corner. +
+ ), firstNameValidationMsg: ( <>

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 0f9f66b589..10caa969ab 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 @@ -24,7 +24,8 @@ import { PathAssociateWithModule, QueryParams, RangerPolicyType, - ServiceType + ServiceType, + policyConditionDisplayLabel } from "Utils/XAEnums"; import { filter, @@ -1585,3 +1586,53 @@ export const currentTimeZone = (timeZoneDate) => { .replace(/^.*GMT.*\(/, "") .replace(/\)$/, ""); }; + +// Common function to get display label for policy condition +export const getPolicyConditionDisplayLbl = (lbl) => { + return has(policyConditionDisplayLabel, lbl) + ? policyConditionDisplayLabel[lbl] + : lbl; +}; + +// Common function to safeguard JSON parsing +export const safeJsonParse = (value, fallback) => { + try { + return JSON.parse(value); + } catch (error) { + console.error("JSON Parsing Error:", error); + return fallback; + } +}; + +//CommonFunction to get display label for policy permission item +export const getPolicyPermissionItemDisplayLbl = ( + serviceDef, + policyType, + accessType +) => { + let accessTypeDefVal = []; + const accesTypeKeys = map(accessType, (item) => { + return isObject(item) ? item.type : item; + }); + if (RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value == policyType) { + accessTypeDefVal = serviceDef.dataMaskDef.accessTypes; + } else if ( + RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value == policyType + ) { + accessTypeDefVal = serviceDef.rowFilterDef.accessTypes; + } else { + accessTypeDefVal = serviceDef.accessTypes; + } + if (serviceDef.name == "tag") { + return map(sortBy(accesTypeKeys), (val) => ({ label: val })); + } else { + if (accessType.length == accessTypeDefVal.length) { + return sortBy(accessTypeDefVal, "label"); + } else { + const accessTypeDisplayLblObj = filter(accessTypeDefVal, (item) => + includes(accesTypeKeys, { type: item.name }) + ); + return sortBy(accessTypeDisplayLblObj, "label"); + } + } +}; diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx index 2c96e1559b..e683303a1b 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx @@ -24,7 +24,12 @@ import { RangerPolicyType, DefStatus } from "Utils/XAEnums"; import dateFormat from "dateformat"; import { toast } from "react-toastify"; import { cloneDeep, find, isEmpty, map, sortBy } from "lodash"; -import { getResourcesDefVal, serverError } from "Utils/XAUtils"; +import { + getResourcesDefVal, + serverError, + getPolicyConditionDisplayLbl, + getPolicyPermissionItemDisplayLbl +} from "Utils/XAUtils"; import { ModalLoader } from "Components/CommonComponents"; import { getServiceDef } from "Utils/appState"; @@ -377,7 +382,7 @@ export function PolicyViewDetails(props) { Select User {!isEmpty( filterServiceDef && filterServiceDef.policyConditions - ) && Policy Conditions} + ) && Rule Conditions} {policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value ? "Permissions" @@ -450,7 +455,7 @@ export function PolicyViewDetails(props) { {!isEmpty( filterServiceDef && filterServiceDef.policyConditions ) && ( - + {!isEmpty(items.conditions) ? items.conditions.map((obj, index) => { let conditionObj = @@ -458,15 +463,13 @@ export function PolicyViewDetails(props) { return e.name == obj.type; }); return ( -

- {`${conditionObj.label}: ${obj.values.join( - ", " - )}`} -
+ {`${getPolicyConditionDisplayLbl( + conditionObj.label + )}: ${obj.values.join(", ")}`} ); }) : "--"} @@ -476,14 +479,18 @@ export function PolicyViewDetails(props) { {!isEmpty(items.accesses) ? ( {" "} - {items.accesses.map((obj, index) => ( + {getPolicyPermissionItemDisplayLbl( + filterServiceDef, + policyType, + items.accesses + ).map((obj, index) => (
- {obj.type} + {obj.label}
))} @@ -548,7 +555,9 @@ export function PolicyViewDetails(props) { const getConditionLabel = (label) => { let filterLabel = find(serviceDef.policyConditions, { name: label }); - return filterLabel && filterLabel?.label ? filterLabel.label : ""; + return filterLabel && filterLabel?.label + ? getPolicyConditionDisplayLbl(filterLabel.label) + : ""; }; return ( !isEmpty(conditions) && ( @@ -559,8 +568,12 @@ export function PolicyViewDetails(props) { {conditions.map((obj) => ( - {getConditionLabel(obj.type)} - {obj.values.join(", ")} + {getConditionLabel(obj.type)} + + + {obj.values.join(", ")} + + ))} @@ -682,14 +695,14 @@ export function PolicyViewDetails(props) { {getPolicyConditions(conditions, serviceDef)} {policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value && ( <> -

Allow Conditions :

+

Allow Rules :

{getFilterPolicy( policyItems, serviceDef, serviceType, - ` No policy items of "Allow Conditions" are present` + ` No policy items of "Allow Rules" are present` )}
@@ -700,7 +713,7 @@ export function PolicyViewDetails(props) { {policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value && serviceDef?.options?.enableDenyAndExceptionsInPolicies == "true" && ( <> -

Exclude from Allow Conditions :

+

Exclude from Allow Rules :

@@ -742,7 +755,7 @@ export function PolicyViewDetails(props) { policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value && serviceDef?.options?.enableDenyAndExceptionsInPolicies == "true" && ( <> -

Deny Conditions :

+

Deny Rules :

@@ -764,7 +777,7 @@ export function PolicyViewDetails(props) { policyType == RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value && serviceDef?.options?.enableDenyAndExceptionsInPolicies == "true" && ( <> -

Exclude from Deny Conditions :

+

Exclude from Deny Rules :

@@ -783,14 +796,14 @@ export function PolicyViewDetails(props) { )} {policyType == RangerPolicyType.RANGER_ROW_FILTER_POLICY_TYPE.value && ( <> -

Row Level Conditions :

+

Row Level Rules :

{getFilterPolicy( rowFilterPolicyItems, serviceDef, serviceType, - `No policy items of "Row Level Conditions" are present` + `No policy items of "Row Level Rules" are present` )}
@@ -798,7 +811,7 @@ export function PolicyViewDetails(props) { )} {policyType == RangerPolicyType.RANGER_MASKING_POLICY_TYPE.value && ( <> -

Masking Conditions :

+

Masking Rules :

{getFilterPolicy( diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx index 2d20250ee4..6031de4747 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/AccessGrantForm.jsx @@ -608,6 +608,7 @@ function AccessGrantForm({ isMulti: true }} isGDS={true} + popOverheader="Policy Conditions" /> )} @@ -728,6 +729,7 @@ function AccessGrantForm({ inputVal={input} showModal={showModal} handleCloseModal={policyConditionState} + modalHeader="Policy Conditions" /> )} /> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx index dd0a0d6318..94a202cfb7 100755 --- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Datashare/DatashareDetailLayout.jsx @@ -1393,6 +1393,7 @@ const DatashareDetailLayout = () => { inputVal={input} showModal={showModal} handleCloseModal={policyConditionState} + modalHeader="Policy Conditions" /> )} /> 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 98d7d31507..791b25ab1e 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 @@ -71,7 +71,8 @@ import { getResourcesDefVal, getAllTimeZoneList, policyConditionUpdatedJSON, - policyInfo + policyInfo, + getPolicyConditionDisplayLbl } from "Utils/XAUtils"; import { useAccordionButton } from "react-bootstrap/AccordionButton"; import AccordionContext from "react-bootstrap/AccordionContext"; @@ -592,7 +593,7 @@ export default function AddUpdatePolicyForm() { type: conditionKey, values: isArray(conditionValue) ? conditionValue.map((m) => { - return m.value; + return m; }) : [conditionValue] }); @@ -711,9 +712,7 @@ export default function AddUpdatePolicyForm() { if (!isEmpty(conditionObj.uiHint)) { obj.conditions[data?.type] = JSON.parse(conditionObj.uiHint) .isMultiValue - ? data?.values.map((m) => { - return { value: m.trim(), label: m.trim() }; - }) + ? data?.values : data?.values.toString().trim(); } } @@ -1509,6 +1508,7 @@ export default function AddUpdatePolicyForm() { handleCloseModal={ policyConditionState } + modalHeader="Policy Conditions" /> )} /> @@ -1547,23 +1547,25 @@ export default function AddUpdatePolicyForm() { return ( @@ -1574,7 +1576,9 @@ export default function AddUpdatePolicyForm() { ) : ( )} @@ -1589,7 +1593,11 @@ export default function AddUpdatePolicyForm() { {isMultiResources && ( <>
-

Resources :

+

+ {serviceCompDetails.name == "tag" + ? "Tags :" + : "Resources :"} +

<> @@ -1656,7 +1664,7 @@ export default function AddUpdatePolicyForm() { <>

- Allow Conditions:{" "} + Allow Rules:{" "}

@@ -1684,7 +1692,7 @@ export default function AddUpdatePolicyForm() {

- Exclude from Allow Conditions: + Exclude from Allow Rules:

@@ -1750,7 +1758,7 @@ export default function AddUpdatePolicyForm() { <>

- Deny Conditions: + Deny Rules:

@@ -1776,7 +1784,7 @@ export default function AddUpdatePolicyForm() {

- Exclude from Deny Conditions: + Exclude from Deny Rules:

@@ -1811,7 +1819,7 @@ export default function AddUpdatePolicyForm() { <>

- Mask Conditions: + Mask Rules:

@@ -1843,7 +1851,7 @@ export default function AddUpdatePolicyForm() { <>

- Row Filter Conditions: + Row Filter Rules:

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 8b2240e2e0..f39bbac8e4 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 @@ -32,8 +32,13 @@ import { const esprima = require("esprima"); export default function PolicyConditionsComp(props) { - const { policyConditionDetails, inputVal, showModal, handleCloseModal } = - props; + const { + policyConditionDetails, + inputVal, + showModal, + handleCloseModal, + modalHeader + } = props; const accessedOpt = [ { value: "yes", label: "Yes" }, @@ -55,7 +60,7 @@ export default function PolicyConditionsComp(props) { }; const formInitialData = () => { - var conditions = {}; + let conditions = {}; if (inputVal && inputVal.value) { for (let val in inputVal.value) { conditions[val] = inputVal.value[val]; @@ -125,11 +130,11 @@ export default function PolicyConditionsComp(props) { >
( - Policy Condition + {modalHeader} {policyConditionDetails?.length > 0 && @@ -199,7 +204,7 @@ export default function PolicyConditionsComp(props) { : "form-control" } as="textarea" - rows={3} + rows={12} onBlur={(e) => trimInputValue(e, input) } @@ -243,10 +248,6 @@ export default function PolicyConditionsComp(props) { onCreateOption={(inputValue) => { const trimmedValue = inputValue.trim(); if (trimmedValue) { - const newOption = { - label: trimmedValue, - value: trimmedValue - }; const currentValues = input.value || []; const newValues = [ ...currentValues, 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 69325c2dd3..92ef1fb3c9 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 @@ -31,7 +31,8 @@ import { map, filter, some, - isEqual + isEqual, + sortBy } from "lodash"; import { toast } from "react-toastify"; import Editable from "Components/Editable"; @@ -42,9 +43,15 @@ import { dragEnter, drop, dragOver, - policyConditionUpdatedJSON + policyConditionUpdatedJSON, + getPolicyConditionDisplayLbl, + safeJsonParse } from "Utils/XAUtils"; -import { selectInputCustomStyles } from "Components/CommonComponents"; +import { + selectInputCustomStyles, + ConfirmationClearIndicator +} from "Components/CommonComponents"; +import PolicyConditionsComp from "./PolicyConditionsComp"; const noneOptions = { label: "None", @@ -72,11 +79,12 @@ export default function PolicyPermissionItem(props) { const [roleLoading, setRoleLoading] = useState(false); const [groupLoading, setGroupLoading] = useState(false); const [userLoading, setUserLoading] = useState(false); + const [activeConditionRow, setActiveConditionRow] = useState(null); const permList = ["Select Roles", "Select Groups", "Select Users"]; if (serviceCompDetails?.policyConditions?.length > 0) { - permList.push("Policy Conditions"); + permList.push("Rule Conditions"); } permList.push("Permissions"); if ( @@ -100,7 +108,14 @@ export default function PolicyPermissionItem(props) { const tableHeader = () => { return permList.map((data) => { - return
; + return ( + + ); }); }; @@ -184,10 +199,10 @@ export default function PolicyPermissionItem(props) { } } } - return srcOp.map(({ label, name: value }) => ({ - label, - value - })); + return sortBy( + srcOp.map(({ label, name: value }) => ({ label, value })), + serviceCompDetails?.name == "tag" ? "value" : "label" + ); }; const getMaskingAccessTypeOptions = (index) => { @@ -244,10 +259,10 @@ export default function PolicyPermissionItem(props) { if ((users || grps || roles) && !accTypes) { if (delegateAdmin !== undefined && delegateAdmin === false) { error = - "Please select permision item for selected users/groups/roles"; + "Please select permission item for selected users/groups/roles"; } else if (delegateAdmin == undefined) { error = - "Please select permision item for selected users/groups/roles"; + "Please select permission item for selected users/groups/roles"; } } if (accTypes && !users && !grps && !roles) { @@ -278,7 +293,7 @@ export default function PolicyPermissionItem(props) { !roles ) { error = - "Please select user/group/role for the entered policy condition"; + "Please select user/group/role for the entered Rule Condition"; } } return error; @@ -289,7 +304,6 @@ export default function PolicyPermissionItem(props) { ...selectInputCustomStyles, control: (base) => ({ ...base, - width: 200, whiteSpace: "nowrap" }) }; @@ -318,10 +332,50 @@ export default function PolicyPermissionItem(props) { }); }; + const ruleConditionDisplayValue = (value) => { + const selectVal = value; + let ipRangVal, uiHintVal; + if (selectVal) { + return Object.keys(selectVal).map((property) => { + let conditionObj = find( + serviceCompDetails.policyConditions, + function (m) { + if (m.name == property) { + return m; + } + } + ); + if (conditionObj?.uiHint && conditionObj?.uiHint != "") { + uiHintVal = safeJsonParse(conditionObj.uiHint, {}); + } + if (isArray(selectVal[property])) { + ipRangVal = (selectVal[property] || []).map((m) => m).join(", "); + } + return ( +
+ + + {`${getPolicyConditionDisplayLbl(conditionObj.label)}: ${ + isArray(selectVal[property]) ? ipRangVal : selectVal[property] + }`} + + +
+ ); + }); + } + }; + return (
-
+
-
- {conditionObj.label} -
+ + {getPolicyConditionDisplayLbl( + conditionObj.label + )} +
{isArray( values?.conditions[keyName] ) ? ( -
+ {values.conditions[ keyName ].join(", ")} -
+ ) : ( -
+ {values.conditions[keyName]} -
+ )}
-
No Conditions
+
+ No Conditions +
{data} + {data} +
{tableHeader()} - + @@ -354,7 +408,7 @@ export default function PolicyPermissionItem(props) { className="form-control" name={`${name}.roles`} render={({ input }) => ( -
+
)} @@ -387,7 +446,7 @@ export default function PolicyPermissionItem(props) { className="form-control" name={`${name}.groups`} render={({ input }) => ( -
+
)} @@ -420,7 +484,7 @@ export default function PolicyPermissionItem(props) { className="form-control" name={`${name}.users`} render={({ input }) => ( -
+
)} @@ -446,7 +515,7 @@ export default function PolicyPermissionItem(props) { ); } - if (colName == "Policy Conditions") { + if (colName == "Rule Conditions") { return ( serviceCompDetails?.policyConditions?.length > 0 && ( @@ -460,19 +529,81 @@ export default function PolicyPermissionItem(props) { index ) } - render={({ input }) => ( -
- { + const showConditionsModal = + activeConditionRow === name; + const hasValue = + Object.keys(input?.value || {}).length !== + 0; + + return ( + <> + {/* Only render modal for the clicked row */} + {showConditionsModal && ( +
+ + setActiveConditionRow(null) + } + modalHeader="Rule Conditions" + /> +
)} - selectProps={{ isMulti: true }} - /> -
- )} + +
+
+
+ {hasValue ? ( + + setActiveConditionRow(name) + } + > + {ruleConditionDisplayValue( + input.value + )} + + ) : ( + + setActiveConditionRow(name) + } + > + Add Conditions + + )} + + +
+
+
+ + ); + }} /> ) @@ -548,6 +679,7 @@ export default function PolicyPermissionItem(props) { options={accessTypeOptions} showSelectAll={true} selectAllLabel="Select All" + popOverheader="Add/Edit Permissions" />
); @@ -583,6 +715,7 @@ export default function PolicyPermissionItem(props) { fields?.value[index]?.accesses ?.tableList } + popOverheader="Select Masking Option" /> {fields?.value[index]?.dataMaskInfo ?.label == "Custom" && ( @@ -610,7 +743,7 @@ export default function PolicyPermissionItem(props) { )}
) : ( -
+
Select Masking Option @@ -650,6 +783,7 @@ export default function PolicyPermissionItem(props) { options={getMaskingAccessTypeOptions()} showSelectAll={false} selectAllLabel="Select All" + popOverheader="Select Masking Option" /> {fields?.value[index]?.dataMaskInfo ?.label == "Custom" && ( @@ -694,6 +828,7 @@ export default function PolicyPermissionItem(props) { {...input} placement="auto" type="input" + popOverheader="Enter Filter Expression" /> {meta.touched && meta.error && ( {meta.error} @@ -712,6 +847,7 @@ export default function PolicyPermissionItem(props) {
; })} - {!isEmpty(props?.serviceDef?.policyConditions) && ( - + {props?.serviceDef?.name != "tag" && ( + + )} ); }); @@ -357,7 +378,7 @@ function PolicyConditionData(props) { @@ -372,7 +393,11 @@ function PolicyConditionData(props) { let access = []; if (!isEmpty(policyItem)) { tableRow = policyItem?.map((items, index) => { - access = items.accesses?.map((obj) => obj.type); + access = getPolicyPermissionItemDisplayLbl( + props.serviceDef, + 1, + items.accesses + )?.map((obj) => obj.label); return ( {!isEmpty(props?.serviceDef?.policyConditions) && ( - + {!isEmpty(props?.serviceDef?.policyConditions) && ( + + )}
{colName}
+
@@ -326,17 +335,20 @@ function PolicyConditionData(props) { )} + {!isEmpty(items.conditions) ? items.conditions.map((obj, index) => { + let conditionObj = props.serviceDef.policyConditions.find( + (condition) => condition.name === obj.type + ); return ( -
- {`${obj.type}: ${obj.values.join(", ")}`} -
+ {`${getPolicyConditionDisplayLbl( + conditionObj.label + )}: ${obj.values.join(", ")}`} ); }) : "--"} @@ -349,6 +361,15 @@ function PolicyConditionData(props) {
--
)}
+ +
"No data to show!!"
@@ -397,17 +422,20 @@ function PolicyConditionData(props) { )} + {!isEmpty(items.conditions) ? items.conditions.map((obj, index) => { + let conditionObj = props.serviceDef.policyConditions.find( + (condition) => condition.name === obj.type + ); return ( -
- {`${obj.type}: ${obj.values.join(", ")}`} -
+ {`${getPolicyConditionDisplayLbl( + conditionObj.label + )}: ${obj.values.join(", ")}`} ); }) : "--"} @@ -454,7 +482,11 @@ function PolicyConditionData(props) { let access = []; if (!isEmpty(policyItem)) { tableRow = policyItem?.map((items, index) => { - access = items.accesses?.map((obj) => obj.type); + access = getPolicyPermissionItemDisplayLbl( + props.serviceDef, + 2, + items.accesses + )?.map((obj) => obj.label); return (
@@ -478,6 +510,26 @@ function PolicyConditionData(props) {
--
)}
+ {!isEmpty(items.conditions) + ? items.conditions.map((obj, index) => { + let conditionObj = props.serviceDef.policyConditions.find( + (condition) => condition.name === obj.type + ); + return ( + {`${getPolicyConditionDisplayLbl( + conditionObj.label + )}: ${obj.values.join(", ")}`} + ); + }) + : "--"} + {!isEmpty(access) ? ( @@ -515,7 +567,7 @@ function PolicyConditionData(props) { {props.policyData.policyType == 0 && ( <> -

Allow Conditions

+

Allow Rules

Groups {!isEmpty(props?.serviceDef?.policyConditions) && ( - + )} - + + {props?.serviceDef?.name != "tag" && } {getPolicyData(props.policyData.policyItems)} @@ -541,7 +592,7 @@ function PolicyConditionData(props) { {props.serviceDef?.options?.enableDenyAndExceptionsInPolicies == "true" && ( <> -

Allow Exclude

+

Allow Exclude Rules

Users - Policy Conditions - Rule ConditionsAccessesPermissionsDelegate Admin
Users {!isEmpty(props?.serviceDef?.policyConditions) && ( )} - + + {props?.serviceDef?.name != "tag" && ( + + )} @@ -566,7 +620,7 @@ function PolicyConditionData(props) {
- Policy Conditions + Rule Conditions AccessesPermissionsDelegate Admin
-

Deny Conditions

+

Deny Rules

Users {!isEmpty(props?.serviceDef?.policyConditions) && ( )} - + + {props?.serviceDef?.name != "tag" && ( + + )} @@ -591,7 +648,7 @@ function PolicyConditionData(props) {
- Policy Conditions + Rule Conditions AccessesPermissionsDelegate Admin
-

Deny Exclude

+

Deny Exclude Rules

Users {!isEmpty(props?.serviceDef?.policyConditions) && ( )} - + + {props?.serviceDef?.name != "tag" && ( + + )} @@ -623,7 +683,7 @@ function PolicyConditionData(props) { {props.policyData.policyType == 1 && ( <> -

Masking Conditions

+

Mask Rules

- Policy Conditions + Rule Conditions AccessesPermissionsDelegate Admin
Groups {!isEmpty(props?.serviceDef?.policyConditions) && ( - + )} - + @@ -654,7 +712,7 @@ function PolicyConditionData(props) { {props.policyData.policyType == 2 && ( <> -

Row Level Conditions

+

Row Filter Rules

Users - Policy Conditions - Rule ConditionsAccessesPermissions Masking Condition
Roles - + {!isEmpty(props?.serviceDef?.policyConditions) && ( + + )} + diff --git a/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx b/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx index 5dc1c6914d..f9fe792f99 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/Reports/UserAccessLayout.jsx @@ -494,7 +494,7 @@ function UserAccessLayout() { ( 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 7d9ad9d31d..817320331c 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 @@ -49,7 +49,8 @@ import { scrollToError, selectInputCustomStyles, selectInputCustomErrorStyles, - trimInputValue + trimInputValue, + ConfirmationClearIndicator } from "Components/CommonComponents"; import usePrompt from "Hooks/usePrompt"; import { getServiceDef } from "Utils/appState"; @@ -873,11 +874,13 @@ const SecurityZoneForm = () => { isMulti components={{ DropdownIndicator: () => null, - IndicatorSeparator: () => null + IndicatorSeparator: () => null, + ClearIndicator: ConfirmationClearIndicator }} isClearable={true} placeholder="Select Users" tabSelectsValue={false} + clearConfirmMessage="Users" /> @@ -918,11 +921,13 @@ const SecurityZoneForm = () => { isMulti components={{ DropdownIndicator: () => null, - IndicatorSeparator: () => null + IndicatorSeparator: () => null, + ClearIndicator: ConfirmationClearIndicator }} isClearable={true} placeholder="Select Groups" tabSelectsValue={false} + clearConfirmMessage="Groups" /> @@ -963,11 +968,13 @@ const SecurityZoneForm = () => { isMulti components={{ DropdownIndicator: () => null, - IndicatorSeparator: () => null + IndicatorSeparator: () => null, + ClearIndicator: ConfirmationClearIndicator }} isClearable={true} placeholder="Select Roles" tabSelectsValue={false} + clearConfirmMessage="Roles" /> {meta.touched && meta.error && ( @@ -1013,11 +1020,13 @@ const SecurityZoneForm = () => { isMulti components={{ DropdownIndicator: () => null, - IndicatorSeparator: () => null + IndicatorSeparator: () => null, + ClearIndicator: ConfirmationClearIndicator }} isClearable={true} placeholder="Select Users" tabSelectsValue={false} + clearConfirmMessage="Users" /> @@ -1058,11 +1067,13 @@ const SecurityZoneForm = () => { isMulti components={{ DropdownIndicator: () => null, - IndicatorSeparator: () => null + IndicatorSeparator: () => null, + ClearIndicator: ConfirmationClearIndicator }} isClearable={true} placeholder="Select Groups" tabSelectsValue={false} + clearConfirmMessage="Groups" /> @@ -1103,11 +1114,13 @@ const SecurityZoneForm = () => { isMulti components={{ DropdownIndicator: () => null, - IndicatorSeparator: () => null + IndicatorSeparator: () => null, + ClearIndicator: ConfirmationClearIndicator }} isClearable={true} placeholder="Select Roles" tabSelectsValue={false} + clearConfirmMessage="Roles" /> {meta.error && meta.touched && ( 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 9468bef967..9ce5dfc378 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 @@ -26,7 +26,7 @@ import AsyncSelect from "react-select/async"; import Editable from "Components/Editable"; import CreatableField from "Components/CreatableField"; import ModalResourceComp from "Views/Resources/ModalResourceComp"; -import { uniq, map, join, isEmpty, isArray } from "lodash"; +import { uniq, map, join, isEmpty, isArray, sortBy } from "lodash"; import TagBasePermissionItem from "Views/PolicyListing/TagBasePermissionItem"; import { dragStart, dragEnter, drop, dragOver } from "Utils/XAUtils"; import { selectInputCustomStyles } from "Components/CommonComponents"; @@ -155,10 +155,10 @@ export default function ServiceAuditFilter(props) { const getAccessTypeOptions = () => { let srcOp = []; srcOp = serviceDefDetails?.accessTypes; - return srcOp?.map(({ label, name: value }) => ({ - label, - value - })); + return sortBy( + srcOp?.map(({ label, name: value }) => ({ label, value })), + serviceDefDetails.name == "tag" ? "value" : "label" + ); }; const permList = [ @@ -388,6 +388,7 @@ export default function ServiceAuditFilter(props) { options={getAccessTypeOptions()} showSelectAll={true} selectAllLabel="Select All" + popOverheader="Add/Edit Permissions" /> )} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx index cc60cd3054..0fb63700eb 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceDefinition.jsx @@ -178,7 +178,7 @@ class ServiceDefinition extends Component { pathname: `/service/${s.id}/policies/${RangerPolicyType.RANGER_ACCESS_POLICY_TYPE.value}`, detail: this.props.selectedZone }} - className="service-name text-info" + className="service-name" > {s.displayName !== undefined ? s.displayName : s.name} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx index cb4d4e65ff..6196cea375 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceForm.jsx @@ -42,7 +42,8 @@ import { Loader, scrollToError, selectInputCustomStyles, - trimInputValue + trimInputValue, + ConfirmationClearIndicator } from "Components/CommonComponents"; import { difference, @@ -706,6 +707,12 @@ class ServiceForm extends Component { isClearable={true} styles={selectInputCustomStyles} isMulti + clearConfirmMessage={ + additionalConfig.type == "user" ? "Users" : "Groups" + } + components={{ + ClearIndicator: ConfirmationClearIndicator + }} /> diff --git a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceViewDetails.jsx b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceViewDetails.jsx index 8cb742c296..9f3afbe91e 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceViewDetails.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/ServiceManager/ServiceViewDetails.jsx @@ -33,6 +33,7 @@ import { } from "lodash"; import { ModalLoader } from "Components/CommonComponents"; import { additionalServiceConfigs } from "Utils/XAEnums"; +import { getPolicyPermissionItemDisplayLbl } from "Utils/XAUtils"; export const ServiceViewDetails = (props) => { const { serviceData: service, serviceDefData } = props; @@ -261,13 +262,17 @@ export const ServiceViewDetails = (props) => {
Groups UsersAccessesRule ConditionsPermissions Row Level Filter
{a.accessTypes !== undefined && a.accessTypes.length > 0 - ? a.accessTypes.map((accessType) => ( + ? getPolicyPermissionItemDisplayLbl( + serviceDefData, + 0, + a.accessTypes + ).map((accessType) => ( - {accessType} + {accessType.label} )) : "--"} diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx index 746ff55a6a..e459c2f123 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleForm.jsx @@ -26,7 +26,8 @@ import { Loader, CustomTooltip, selectInputCustomStyles, - trimInputValue + trimInputValue, + ConfirmationClearIndicator } from "Components/CommonComponents"; import { FieldArray } from "react-final-form-arrays"; import arrayMutators from "final-form-arrays"; @@ -639,6 +640,10 @@ function RoleForm() { styles={selectInputCustomStyles} tabSelectsValue={false} placeholder="Select Users" + clearConfirmMessage="Users" + components={{ + ClearIndicator: ConfirmationClearIndicator + }} />
@@ -748,6 +753,10 @@ function RoleForm() { styles={selectInputCustomStyles} tabSelectsValue={false} placeholder="Select Groups" + clearConfirmMessage="Groups" + components={{ + ClearIndicator: ConfirmationClearIndicator + }} />
@@ -857,6 +866,10 @@ function RoleForm() { styles={selectInputCustomStyles} tabSelectsValue={false} placeholder="Select Roles" + clearConfirmMessage="Roles" + components={{ + ClearIndicator: ConfirmationClearIndicator + }} />
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx index e00333e7d7..068475d0f8 100644 --- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx +++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx @@ -24,7 +24,8 @@ import { BlockUi, scrollToError, selectInputCustomStyles, - trimInputValue + trimInputValue, + ConfirmationClearIndicator } from "Components/CommonComponents"; import AsyncSelect from "react-select/async"; import Select from "react-select"; @@ -244,6 +245,10 @@ function UserForm(props) { styles={selectInputCustomStyles} tabSelectsValue={false} placeholder="Select Groups" + clearConfirmMessage="Groups" + components={{ + ClearIndicator: ConfirmationClearIndicator + }} /> ); };