Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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 (
Expand Down Expand Up @@ -87,12 +95,12 @@ export class MoreLess extends Component {
return (
<>
<div className={this.state.show ? "show-less" : "show-more"}>
{this?.state?.data?.map((key) => {
{this?.state?.data?.map((key, index) => {
return (
<Badge
bg="info"
title={key}
key={key}
key={index}
className="m-1 text-truncate more-less-width"
>
{key}
Expand Down Expand Up @@ -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 (
<>
<selectComponents.ClearIndicator {...rest} innerProps={cleanInnerProps}>
<span
style={{ cursor: "pointer" }}
onMouseDown={open}
title="Clear all"
>
<i className="fa fa-times fa-2"></i>
</span>
</selectComponents.ClearIndicator>

<Modal show={show} onHide={() => setShow(false)}>
<Modal.Body>{message}</Modal.Body>
<Modal.Footer>
<Button variant="secondary" size="sm" onMouseDown={onNo}>
No
</Button>
<Button variant="danger" size="sm" onMouseDown={onYes}>
Yes
</Button>
</Modal.Footer>
</Modal>
</>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -387,7 +387,8 @@ const Editable = (props) => {
options = [],
conditionDefVal,
servicedefName,
isGDS
isGDS,
popOverheader
} = props;

const initialLoad = useRef(true);
Expand Down Expand Up @@ -451,7 +452,9 @@ const Editable = (props) => {
<div
key={property}
className={`${
uiHintVal?.isMultiline ? "editable-label" : "badge bg-dark"
uiHintVal?.isMultiline
? "editable-label rule-condition-wrapper"
: "badge bg-dark"
}`}
>
{`${conditionObj.label}: ${
Expand Down Expand Up @@ -502,7 +505,6 @@ const Editable = (props) => {
variant="outline-dark"
size="sm"
type="button"
s
>
<i className="fa-fw fa fa-plus"></i>
</Button>
Expand All @@ -514,7 +516,7 @@ const Editable = (props) => {
selectVal && selectVal?.length > 0 ? (
<>
<span className="editable-edit-text">
{selectVal.map((op, index) => (
{sortBy(selectVal, "label").map((op, index) => (
<h6 className="d-inline me-1" key={index}>
<Badge bg="info">{op.label}</Badge>
</h6>
Expand Down Expand Up @@ -729,9 +731,7 @@ const Editable = (props) => {
type === TYPE_CHECKBOX && "popover-maxHeight popover-minHeight"
}`}
>
<Popover.Header>
{type === TYPE_CHECKBOX ? "Select" : "Enter"}
</Popover.Header>
<Popover.Header>{popOverheader}</Popover.Header>
<Popover.Body>
{type === TYPE_CHECKBOX ? (
<CheckboxComp
Expand Down
56 changes: 52 additions & 4 deletions security-admin/src/main/webapp/react-webapp/src/styles/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -574,9 +574,14 @@ h3.wrap-header {
margin-top: 5px;
margin-bottom: 5px;
border-radius: 5px;
font-size: 70%;
font-weight: 700;
padding: 3px;
font-size: 14px;
display: block;
}

.rule-condition-wrapper {
white-space: normal;
word-break: break-all;
}

/* Service Manager */
Expand Down Expand Up @@ -630,6 +635,7 @@ table.no-bg-color thead tr th:first-child {
white-space: nowrap;
vertical-align: sub;
display: inline-block;
font-size: 14px;
}

.service-name,
Expand Down Expand Up @@ -676,6 +682,16 @@ table.no-bg-color thead tr th:first-child {
padding: 8px;
}

.table-fixed table {
width: 100%;
table-layout: fixed;
}

.table-fixed .table thead th {
font-size: 13px;
padding: 8px;
}

.bt-1 {
border-top: 1px solid #ddd;
}
Expand Down Expand Up @@ -1592,7 +1608,6 @@ header {
display: inline-flex;
flex-wrap: wrap;
font-size: 1rem;
max-height: 100px;
overflow-y: auto;
width: 100%;
}
Expand All @@ -1602,7 +1617,6 @@ header {
flex-wrap: wrap;
font-size: 1rem;
overflow-y: auto;
max-height: 100px;
width: 100%;
}

Expand Down Expand Up @@ -1654,6 +1668,11 @@ header {
overflow-y: auto;
}

.permission-item {
max-height: 256px;
overflow-y: auto;
}

/* Form control */
.form-control:disabled {
cursor: not-allowed;
Expand Down Expand Up @@ -3021,3 +3040,32 @@ table a {
.switch[class*="btn-outline"] .switch-handle {
background-color: #6c757d !important;
}

.line-clamp-3 {
--line-clamp: 3;
}

.line-clamp-5 {
--line-clamp: 5;
}

.line-clamp {
white-space: normal;
word-break: break-all;
width: 100%;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: var(--line-clamp, 3);
overflow: auto;
line-height: 21px;
}

.condition-group-table td {
font-size: 14px;
color: rgb(33, 37, 41);
}

.condition-group-table th {
font-size: 15px !important;
color: #333;
}
Original file line number Diff line number Diff line change
Expand Up @@ -986,3 +986,8 @@ export const additionalServiceConfigs = [
type: "user"
}
];
export const policyConditionDisplayLabel = {
"Accessed after expiry_date (yes/no)?": "Accessed after expiry date",
"Enter boolean expression": "Boolean expression",
"IP Address Range": "IP Address Range"
};
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,16 @@ export const RegexMessage = {
</p>
</>
),
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:(
<>
<span className="mb-0" style={{ fontSize: "small" }}>
1. Boolean expression Examples:
<br />
country_code == 'USA', time_range &gt;= 900 time_range &lt;= 1800 etc.
<br />
2. The condition editor (textarea) can be resized by dragging its bottom-right corner.
</span>
</>),
firstNameValidationMsg: (
<>
<p className="pd-10 mb-0" style={{ fontSize: "small" }}>
Expand Down
53 changes: 52 additions & 1 deletion security-admin/src/main/webapp/react-webapp/src/utils/XAUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ import {
PathAssociateWithModule,
QueryParams,
RangerPolicyType,
ServiceType
ServiceType,
policyConditionDisplayLabel
} from "Utils/XAEnums";
import {
filter,
Expand Down Expand Up @@ -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");
}
}
};
Loading
Loading