blob: b2997356a151fccdfe480b8c1ad7dc43ab884cae [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, useCallback, useRef } from "react";
import { Link } from "react-router-dom";
import {
Accordion,
Badge,
Button,
Col,
Modal,
Row,
Table
} from "react-bootstrap";
import { isEmpty, find } from "lodash";
import { MoreLess } from "Components/CommonComponents";
import XATableLayout from "Components/XATableLayout";
import { fetchApi } from "Utils/fetchAPI";
import { Loader } from "../../components/CommonComponents";
import { isAuditor, isKMSAuditor } from "../../utils/XAUtils";
function SearchPolicyTable(props) {
const [searchPoliciesData, setSearchPolicies] = useState([]);
const fetchIdRef = useRef(0);
const [loader, setLoader] = useState(true);
const [totalCount, setTotalCount] = useState(0);
const [pageCount, setPageCount] = React.useState(0);
const [policyData, setPolicyData] = useState(null);
const [showModal, setShowModal] = useState(false);
const showPolicyConditionModal = (policyData) => {
setShowModal(true);
setPolicyData(policyData);
};
const hidePolicyConditionModal = () => setShowModal(false);
const fetchSearchPolicies = useCallback(
async ({ pageSize, pageIndex }) => {
setLoader(true);
const fetchId = ++fetchIdRef.current;
let searchPoliciesResp;
let searchPolicies = [];
let totalPoliciesCount = 0;
let params = { ...props.searchParams };
if (fetchId === fetchIdRef.current) {
params["serviceType"] = props.serviceDef.name;
params["pageSize"] = pageSize;
params["startIndex"] = pageIndex * pageSize;
try {
searchPoliciesResp = await fetchApi({
url: `plugins/policies`,
params: params
});
searchPolicies = searchPoliciesResp.data.policies;
totalPoliciesCount = searchPoliciesResp.data.totalCount;
} catch (error) {
`Error occurred while fetching Service Policies ! ${error}`;
}
setSearchPolicies(searchPolicies);
setTotalCount(totalPoliciesCount);
setPageCount(Math.ceil(totalPoliciesCount / pageSize));
setLoader(false);
}
},
[props.searchParams]
);
const getServiceId = (serviceName) => {
let service = find(props.services, { name: serviceName });
return service.id;
};
const columns = React.useMemo(
() => [
{
Header: "Policy ID",
accessor: "id",
Cell: (rawValue) => {
if (isAuditor() || isKMSAuditor()) {
return (
<div className="position-relative text-center">
{rawValue.value}
</div>
);
} else {
return (
<div className="position-relative text-center">
<Link
title="Edit"
to={`/service/${getServiceId(
rawValue.row.original.service
)}/policies/${rawValue.value}/edit`}
>
{rawValue.value}
</Link>
</div>
);
}
},
width: 65
},
{
Header: "Policy Name",
accessor: "name",
Cell: (val) => {
return (
<span
className="text-truncate"
style={{ maxWidth: "120px", display: "inline-block" }}
>
{val.value}
</span>
);
}
},
{
Header: "Policy Label",
accessor: "policyLabels",
Cell: (rawValue) => {
let policyLabels = rawValue?.value?.map((label, index) => (
<span key={index}>{label}</span>
));
return !isEmpty(policyLabels) ? (
<MoreLess data={policyLabels} key={rawValue.row.original.id} />
) : (
<div className="text-center">--</div>
);
}
},
{
Header: "Resources",
accessor: "resources",
Cell: (rawValue) => {
if (rawValue.value) {
let keyName = Object.keys(rawValue.value);
return keyName?.map((key, index) => {
let val = rawValue.value[key].values;
return (
<div key={index} className="text-center overflow-text">
<b>{key}: </b>
{val.join()}
</div>
);
});
}
}
},
{
Header: "Policy Type",
accessor: "policyType",
Cell: (rawValue) => {
if (rawValue.value == 1) {
return (
<h6 className="text-center">
<Badge bg="primary">Masking</Badge>
</h6>
);
} else if (rawValue.value == 2) {
return (
<h6 className="text-center">
<Badge bg="primary">Row Level Filter</Badge>
</h6>
);
} else
return (
<h6 className="text-center">
<Badge bg="primary">Access</Badge>
</h6>
);
}
},
{
Header: "Status",
accessor: "isEnabled",
Cell: (rawValue) => {
if (rawValue.value)
return (
<h6 className="text-center">
<Badge bg="success">Enabled</Badge>
</h6>
);
else
return (
<h6 className="text-center">
<Badge bg="danger">Disabled</Badge>
</h6>
);
}
},
{
Header: "Zone Name",
accessor: "zoneName",
Cell: (rawValue) => {
return !isEmpty(rawValue.value) ? (
<Badge bg="dark" className="text-truncate mw-100">
{rawValue.value}
</Badge>
) : (
<div className="text-center">--</div>
);
}
},
{
Header: "Policy Conditions",
Cell: ({ row: { original } }) => {
return (
<div className="text-center">
<Button
variant="outline-dark"
size="sm"
title="View"
onClick={(e) => {
e.stopPropagation();
showPolicyConditionModal(original);
}}
>
<div className="text-center">
<i className="fa-fw fa fa-plus"></i>
</div>
</Button>
</div>
);
}
}
],
[]
);
return (
<Row>
<Col sm={12} className="mt-3">
<Accordion defaultActiveKey="0">
<Accordion.Item eventKey="0">
<Accordion.Header data-js="hdfsHeader" data-cy="hdfsHeader">
<div className="clearfix">
<span className="bold float-start text-uppercase">
{props.serviceDef.name}
</span>
<span className="float-end"></span>
</div>
</Accordion.Header>
<Accordion.Body>
{props.contentLoader ? (
<Loader />
) : (
<XATableLayout
columnHide={false}
loading={loader}
data={searchPoliciesData}
columns={columns}
fetchData={fetchSearchPolicies}
pagination
pageCount={pageCount}
totalCount={totalCount}
/>
)}
</Accordion.Body>
</Accordion.Item>
</Accordion>
<Modal show={showModal} onHide={hidePolicyConditionModal} size="lg">
<Modal.Header closeButton>
<Modal.Title>Policy Condition Details</Modal.Title>
</Modal.Header>
<Modal.Body>
<PolicyConditionData
policyData={policyData}
serviceDef={props.serviceDef}
/>
</Modal.Body>
</Modal>
</Col>
</Row>
);
}
export default SearchPolicyTable;
function PolicyConditionData(props) {
const getPolicyData = (policyItem) => {
let tableRow = [];
let access = [];
if (!isEmpty(policyItem)) {
tableRow = policyItem?.map((items, index) => {
access = items.accesses?.map((obj) => obj.type);
return (
<tr key={index}>
<td>
{!isEmpty(items.roles) ? (
<MoreLess data={items.roles} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.groups) ? (
<MoreLess data={items.groups} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.users) ? (
<MoreLess data={items.users} />
) : (
<div className="text-center">--</div>
)}
</td>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<td className="text-center">
{!isEmpty(items.conditions)
? items.conditions.map((obj, index) => {
return (
<h6 className="d-inline me-1" key={index}>
<Badge
bg="info"
className="d-inline me-1"
key={obj.values}
>{`${obj.type}: ${obj.values.join(", ")}`}</Badge>
</h6>
);
})
: "--"}
</td>
)}
<td>
{!isEmpty(access) ? (
<MoreLess data={access} />
) : (
<div className="text-center">--</div>
)}
</td>
</tr>
);
});
} else {
tableRow.push(
<tr key="no-data">
<td
className="text-center"
colSpan={!isEmpty(props?.serviceDef?.policyConditions) ? "5" : "4"}
>
<span className="text-muted">&quot;No data to show!!&quot;</span>
</td>
</tr>
);
}
return tableRow;
};
const getMaskingPolicyData = (policyItem) => {
let tableRow = [];
let access = [];
if (!isEmpty(policyItem)) {
tableRow = policyItem?.map((items, index) => {
access = items.accesses?.map((obj) => obj.type);
return (
<tr key={index}>
<td>
{!isEmpty(items.roles) ? (
<MoreLess data={items.roles} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.groups) ? (
<MoreLess data={items.groups} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.users) ? (
<MoreLess data={items.users} />
) : (
<div className="text-center">--</div>
)}
</td>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<td className="text-center">
{!isEmpty(items.conditions)
? items.conditions.map((obj, index) => {
return (
<h6 className="d-inline me-1" key={index}>
<Badge
bg="info"
className="d-inline me-1"
key={obj.values}
>{`${obj.type}: ${obj.values.join(", ")}`}</Badge>
</h6>
);
})
: "--"}
</td>
)}
<td>
{!isEmpty(access) ? (
<MoreLess data={access} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.dataMaskInfo) ? (
<h6 className="d-inline">
<Badge bg="info" className="me-1">
{items.dataMaskInfo["dataMaskType"]}
</Badge>
</h6>
) : (
"--"
)}
</td>
</tr>
);
});
} else {
tableRow.push(
<tr key="no-data">
<td
className="text-center"
colSpan={!isEmpty(props?.serviceDef?.policyConditions) ? "5" : "4"}
>
<span className="text-muted">&quot;No data to show!!&quot;</span>
</td>
</tr>
);
}
return tableRow;
};
const getRowLevelPolicyData = (policyItem) => {
let tableRow = [];
let access = [];
if (!isEmpty(policyItem)) {
tableRow = policyItem?.map((items, index) => {
access = items.accesses?.map((obj) => obj.type);
return (
<tr key={index}>
<td>
{!isEmpty(items.roles) ? (
<MoreLess data={items.roles} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.groups) ? (
<MoreLess data={items.groups} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.users) ? (
<MoreLess data={items.users} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(access) ? (
<MoreLess data={access} />
) : (
<div className="text-center">--</div>
)}
</td>
<td>
{!isEmpty(items.rowFilterInfo) ? (
<h6 className="d-inline">
<Badge bg="info" className="me-1">
{items.rowFilterInfo["filterExpr"]}
</Badge>
</h6>
) : (
"--"
)}
</td>
</tr>
);
});
} else {
tableRow.push(
<tr key="no-data">
<td className="text-center" colSpan="4">
<span className="text-muted">&quot;No data to show!!&quot;</span>
</td>
</tr>
);
}
return tableRow;
};
return (
<React.Fragment>
{props.policyData.policyType == 0 && (
<>
<p className="form-header">Allow Conditions</p>
<div className="overflow-x-auto">
<Table
bordered
size="sm"
className="mb-3 table-audit-filter-ready-only"
>
<thead>
<tr>
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<th className="text-center text-nowrap">
Policy Conditions
</th>
)}
<th>Accesses</th>
</tr>
</thead>
<tbody>{getPolicyData(props.policyData.policyItems)}</tbody>
</Table>
</div>
{props.serviceDef?.options?.enableDenyAndExceptionsInPolicies ==
"true" && (
<>
<p className="form-header">Allow Exclude</p>
<div className="overflow-x-auto">
<Table
bordered
size="sm"
className="mb-3 table-audit-filter-ready-only"
>
<thead>
<tr>
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<th className="text-center text-nowrap">
Policy Conditions
</th>
)}
<th>Accesses</th>
</tr>
</thead>
<tbody>
{getPolicyData(props.policyData.allowExceptions)}
</tbody>
</Table>
</div>
<p className="form-header">Deny Conditions</p>
<div className="overflow-x-auto">
<Table
bordered
size="sm"
className="mb-3 table-audit-filter-ready-only"
>
<thead>
<tr>
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<th className="text-center text-nowrap">
Policy Conditions
</th>
)}
<th>Accesses</th>
</tr>
</thead>
<tbody>
{getPolicyData(props.policyData.denyPolicyItems)}
</tbody>
</Table>
</div>
<p className="form-header">Deny Exclude</p>
<div className="overflow-x-auto">
<Table
bordered
size="sm"
className="mb-3 table-audit-filter-ready-only"
>
<thead>
<tr>
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<th className="text-center text-nowrap">
Policy Conditions
</th>
)}
<th>Accesses</th>
</tr>
</thead>
<tbody>
{getPolicyData(props.policyData.denyExceptions)}
</tbody>
</Table>
</div>
</>
)}
</>
)}
{props.policyData.policyType == 1 && (
<>
<p className="form-header ">Masking Conditions</p>
<div className="overflow-x-auto">
<Table
bordered
size="sm"
className="mb-3 table-audit-filter-ready-only"
>
<thead>
<tr>
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
{!isEmpty(props?.serviceDef?.policyConditions) && (
<th className="text-center text-nowrap">
Policy Conditions
</th>
)}
<th>Accesses</th>
<th>Masking Condition</th>
</tr>
</thead>
<tbody>
{getMaskingPolicyData(props.policyData.dataMaskPolicyItems)}
</tbody>
</Table>
</div>
</>
)}
{props.policyData.policyType == 2 && (
<>
<p className="form-header">Row Level Conditions</p>
<div className="overflow-x-auto">
<Table
bordered
size="sm"
className="mb-3 table-audit-filter-ready-only"
>
<thead>
<tr>
<th>Roles</th>
<th>Groups</th>
<th>Users</th>
<th>Accesses</th>
<th>Row Level Filter</th>
</tr>
</thead>
<tbody>
{getRowLevelPolicyData(props.policyData.rowFilterPolicyItems)}
</tbody>
</Table>
</div>
</>
)}
</React.Fragment>
);
}