RANGER-4518 : Improvement in state management for search filter parameters in Ranger React (#691)
diff --git a/security-admin/src/main/webapp/react-webapp/src/App.jsx b/security-admin/src/main/webapp/react-webapp/src/App.jsx
index a200db6..501daab 100755
--- a/security-admin/src/main/webapp/react-webapp/src/App.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/App.jsx
@@ -21,10 +21,10 @@
import { Route, Routes, HashRouter } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import axios from "axios";
-import { hasAccessToTab, isUser } from "./utils/XAUtils";
+import { hasAccessToTab, isUser } from "Utils/XAUtils";
import ErrorBoundary from "Views/ErrorBoundary";
-import ErrorPage from "./views/ErrorPage";
-import { CommonScrollButton, Loader } from "../src/components/CommonComponents";
+import ErrorPage from "Views/ErrorPage";
+import { CommonScrollButton, Loader } from "Components/CommonComponents";
import history from "Utils/history";
import { setUserProfile, setServiceDef } from "Utils/appState";
import LayoutComp from "Views/Layout";
@@ -35,98 +35,99 @@
const ServiceFormComp = lazy(() => import("Views/ServiceManager/ServiceForm"));
const UserProfileComp = lazy(() => import("Views/UserProfile"));
const ZoneListingComp = lazy(() => import("Views/SecurityZone/ZoneListing"));
-const SecurityZoneFormComp = lazy(
- () => import("Views/SecurityZone/SecurityZoneForm")
+const SecurityZoneFormComp = lazy(() =>
+ import("Views/SecurityZone/SecurityZoneForm")
);
-const UserGroupRoleListing = lazy(
- () => import("Views/UserGroupRoleListing/UserGroupRoleListing")
+const UserGroupRoleListing = lazy(() =>
+ import("Views/UserGroupRoleListing/UserGroupRoleListing")
);
-const UserListingComp = lazy(
- () => import("Views/UserGroupRoleListing/users_details/UserListing")
+const UserListingComp = lazy(() =>
+ import("Views/UserGroupRoleListing/users_details/UserListing")
);
-const GroupListingComp = lazy(
- () => import("Views/UserGroupRoleListing/groups_details/GroupListing")
+const GroupListingComp = lazy(() =>
+ import("Views/UserGroupRoleListing/groups_details/GroupListing")
);
-const RoleListingComp = lazy(
- () => import("Views/UserGroupRoleListing/role_details/RoleListing")
+const RoleListingComp = lazy(() =>
+ import("Views/UserGroupRoleListing/role_details/RoleListing")
);
-const UserForm = lazy(
- () => import("Views/UserGroupRoleListing/users_details/AddUserView")
+const UserForm = lazy(() =>
+ import("Views/UserGroupRoleListing/users_details/AddUserView")
);
-const EditUserView = lazy(
- () => import("Views/UserGroupRoleListing/users_details/EditUserView")
+const EditUserView = lazy(() =>
+ import("Views/UserGroupRoleListing/users_details/EditUserView")
);
-const GroupForm = lazy(
- () => import("Views/UserGroupRoleListing/groups_details/GroupForm")
+const GroupForm = lazy(() =>
+ import("Views/UserGroupRoleListing/groups_details/GroupForm")
);
-const RoleForm = lazy(
- () => import("Views/UserGroupRoleListing/role_details/RoleForm")
+const RoleForm = lazy(() =>
+ import("Views/UserGroupRoleListing/role_details/RoleForm")
);
const Permissions = lazy(() => import("Views/PermissionsModule/Permissions"));
-const EditPermissionComp = lazy(
- () => import("Views/PermissionsModule/EditPermission")
+const EditPermissionComp = lazy(() =>
+ import("Views/PermissionsModule/EditPermission")
);
const AuditLayout = lazy(() => import("Views/AuditEvent/AuditLayout"));
-const AccessLogs = lazy(() => import("Views/AuditEvent/AccessLogs"));
-const AdminLogs = lazy(() => import("Views/AuditEvent/AdminLogs"));
-const LoginSessionsLogs = lazy(
- () => import("Views/AuditEvent/LoginSessionsLogs")
+const AccessLogs = lazy(() => import("Views/AuditEvent/Access/AccessLogs"));
+const AdminLogs = lazy(() => import("Views/AuditEvent/Admin/AdminLogs"));
+const LoginSessionsLogs = lazy(() =>
+ import("Views/AuditEvent/LoginSessions/LoginSessionsLogs")
);
-const PluginsLog = lazy(() => import("Views/AuditEvent/PluginsLog"));
-const PluginStatusLogs = lazy(
- () => import("Views/AuditEvent/PluginStatusLogs")
+const PluginsLogs = lazy(() => import("Views/AuditEvent/Plugins/PluginsLogs"));
+const PluginStatusLogs = lazy(() =>
+ import("Views/AuditEvent/PluginStatus/PluginStatusLogs")
);
-const UserSyncLogs = lazy(() => import("Views/AuditEvent/UserSync"));
-
-const PolicyListingTabView = lazy(
- () => import("Views/PolicyListing/PolicyListingTabView")
+const UserSyncLogs = lazy(() =>
+ import("Views/AuditEvent/UserSync/UserSyncLogs")
);
-const AddUpdatePolicyForm = lazy(
- () => import("Views/PolicyListing/AddUpdatePolicyForm")
+const PolicyListingTabView = lazy(() =>
+ import("Views/PolicyListing/PolicyListingTabView")
+);
+const AddUpdatePolicyForm = lazy(() =>
+ import("Views/PolicyListing/AddUpdatePolicyForm")
);
const EncryptionComp = lazy(() => import("Views/Encryption/KeyManager"));
const KeyCreateComp = lazy(() => import("Views/Encryption/KeyCreate"));
-const AccesLogDetailComp = lazy(
- () => import("Views/AuditEvent/AccessLogDetail")
+const AccessLogDetailComp = lazy(() =>
+ import("Views/AuditEvent/Access/AccessLogDetail")
);
-const UserAccessLayoutComp = lazy(
- () => import("Views/Reports/UserAccessLayout")
+const UserAccessLayoutComp = lazy(() =>
+ import("Views/Reports/UserAccessLayout")
);
-const MyDatasetListingComp = lazy(
- () => import("Views/GovernedData/Dataset/MyDatasetListing")
+const MyDatasetListingComp = lazy(() =>
+ import("Views/GovernedData/Dataset/MyDatasetListing")
);
-const CreateDatasetComp = lazy(
- () => import("Views/GovernedData/Dataset/AddDatasetView")
+const CreateDatasetComp = lazy(() =>
+ import("Views/GovernedData/Dataset/AddDatasetView")
);
-const DatasetDetailLayoutComp = lazy(
- () => import("Views/GovernedData/Dataset/DatasetDetailLayout")
+const DatasetDetailLayoutComp = lazy(() =>
+ import("Views/GovernedData/Dataset/DatasetDetailLayout")
);
-const DatasetDetailFullViewComp = lazy(
- () => import("Views/GovernedData/Dataset/DatasetDetailFullView")
+const DatasetDetailFullViewComp = lazy(() =>
+ import("Views/GovernedData/Dataset/DatasetDetailFullView")
);
-const AccessGrantFormComp = lazy(
- () => import("Views/GovernedData/Dataset/AccessGrantForm")
+const AccessGrantFormComp = lazy(() =>
+ import("Views/GovernedData/Dataset/AccessGrantForm")
);
-const MyDatashareListingComp = lazy(
- () => import("Views/GovernedData/Datashare/MyDatashareListing")
+const MyDatashareListingComp = lazy(() =>
+ import("Views/GovernedData/Datashare/MyDatashareListing")
);
-const CreateDatashareComp = lazy(
- () => import("Views/GovernedData/Datashare/AddDatashareView")
+const CreateDatashareComp = lazy(() =>
+ import("Views/GovernedData/Datashare/AddDatashareView")
);
-const DatashareDetailLayoutComp = lazy(
- () => import("Views/GovernedData/Datashare/DatashareDetailLayout")
+const DatashareDetailLayoutComp = lazy(() =>
+ import("Views/GovernedData/Datashare/DatashareDetailLayout")
);
-const DatashareDetailFullView = lazy(
- () => import("Views/GovernedData/Datashare/DatashareDetailFullView")
+const DatashareDetailFullView = lazy(() =>
+ import("Views/GovernedData/Datashare/DatashareDetailFullView")
);
-const DatashareAddSharedResourceComp = lazy(
- () => import("Views/GovernedData/Datashare/AddSharedResourceComp")
+const DatashareAddSharedResourceComp = lazy(() =>
+ import("Views/GovernedData/Datashare/AddSharedResourceComp")
);
-const GDSRequestListingComp = lazy(
- () => import("Views/GovernedData/Request/RequestListing")
+const GDSRequestListingComp = lazy(() =>
+ import("Views/GovernedData/Request/RequestListing")
);
-const GDSRequestDetailComp = lazy(
- () => import("Views/GovernedData/Request/RequestDetailView")
+const GDSRequestDetailComp = lazy(() =>
+ import("Views/GovernedData/Request/RequestDetailView")
);
export default class App extends Component {
@@ -187,8 +188,8 @@
let serviceDefUrl = hasAccessToTab("Resource Based Policies")
? "plugins/definitions"
: hasAccessToTab("Tag Based Policies") && isUser()
- ? "plugins/definitions/name/tag"
- : "plugins/definitions";
+ ? "plugins/definitions/name/tag"
+ : "plugins/definitions";
try {
getServiceDefData = await fetchApi({
@@ -308,14 +309,14 @@
path="loginSession"
element={<LoginSessionsLogs />}
/>
- <Route path="agent" element={<PluginsLog />} />
+ <Route path="agent" element={<PluginsLogs />} />
<Route path="pluginStatus" element={<PluginStatusLogs />} />
<Route path="userSync" element={<UserSyncLogs />} />
</Route>
{/* AUDIT LOGS DETAILS VIEW */}
<Route
path="/reports/audit/eventlog/:eventId"
- element={<AccesLogDetailComp />}
+ element={<AccessLogDetailComp />}
></Route>
{/* USER/GROUP/ROLE LISTING*/}
<Route path="/users" element={<UserGroupRoleListing />}>
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 85a361d..15b8569 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
@@ -25,7 +25,7 @@
import { useLocation } from "react-router-dom";
import blockLoading from "Images/blockLoading.gif";
-const Loader = () => {
+export const Loader = () => {
return (
<div className="loading-img">
<div id="center">
@@ -187,9 +187,7 @@
export const AuditFilterEntries = (props) => {
const { entries, refreshTable } = props;
- const refreshTables = () => {
- refreshTable();
- };
+
const showPageDetail = (entriesDetails) => {
let startIndex = !isEmpty(entriesDetails) && entriesDetails.startIndex + 1;
let endIndex =
@@ -199,10 +197,11 @@
entriesDetails.totalCount
);
return entriesDetails && entriesDetails.totalCount > 0
- ? `${startIndex} to ${endIndex} of
+ ? `${startIndex} to ${endIndex} of
${entriesDetails.totalCount}`
: 0;
};
+
return (
<div className="row text-end mb-2">
<div className="col-sm-12">
@@ -223,7 +222,7 @@
className="link-tag m-l-xsm"
title="Refresh"
onClick={() => {
- refreshTables();
+ refreshTable();
}}
data-id="refresh"
data-cy="refresh"
@@ -536,11 +535,11 @@
block: "center",
inline: "start"
});
- newRowAdded.bgColor = "#dbe8f7";
+ newRowAdded.classList.add("table-success");
setTimeout(function () {
- newRowAdded.bgColor = "";
- }, 8000);
+ newRowAdded.classList.remove("table-success");
+ }, 4000);
}
};
@@ -569,5 +568,3 @@
</h4>
);
};
-
-export { Loader };
diff --git a/security-admin/src/main/webapp/react-webapp/src/components/XATableLayout.jsx b/security-admin/src/main/webapp/react-webapp/src/components/XATableLayout.jsx
index 950f57c..155b9f4 100644
--- a/security-admin/src/main/webapp/react-webapp/src/components/XATableLayout.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/components/XATableLayout.jsx
@@ -511,7 +511,7 @@
nextPage();
setCurrentPageVal(pageIndex + 2);
}}
- className="pagination-btn-previous me-1 btn btn-outline-dark btn-sm lh-1"
+ className="pagination-btn-previous me-1 btn btn-outline-dark btn-sm"
disabled={!canNextPage}
>
<i className="fa fa-angle-right" aria-hidden="true"></i>
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogDetail.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogDetail.jsx
similarity index 77%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogDetail.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogDetail.jsx
index fda6c4f..a2a0334 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogDetail.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogDetail.jsx
@@ -18,11 +18,11 @@
*/
import React, { useState, useEffect } from "react";
-import AccessLogsTable from "./AccessLogsTable";
-import { PolicyViewDetails } from "./AdminLogs/PolicyViewDetails";
+import AccessLogTable from "./AccessLogTable";
+import { PolicyViewDetails } from "Views/AuditEvent/Admin/AdminLogs/PolicyViewDetails";
import { fetchApi } from "Utils/fetchAPI";
import { toast } from "react-toastify";
-import { isEmpty } from "lodash";
+import { isEmpty, pick } from "lodash";
import { Loader } from "Components/CommonComponents";
import { useParams } from "react-router-dom";
@@ -48,15 +48,17 @@
});
} catch (error) {
console.error(
- `Error occurred while fetching Access or CSRF headers! ${error}`
+ `Error occurred while fetching audit access logs : ${error}`
);
toast.error(error?.response?.data?.msgDesc);
}
- if (!isEmpty(accessResp)) {
+
+ if (!isEmpty(accessResp.data?.vXAccessAudits)) {
accessResp.data.vXAccessAudits.map((obj) => {
accessData = obj;
});
}
+
setAccess(accessData);
setLoader(false);
};
@@ -69,17 +71,24 @@
<>
<h5 className="heading-without-wrap">
{params.eventId !== undefined
- ? "Ranger – audit log"
+ ? "Ranger - Audit Access Log Detail"
: "Audit Access Log Detail"}
</h5>
<div className="wrap">
- <AccessLogsTable data={access}></AccessLogsTable>
+ <AccessLogTable data={access}></AccessLogTable>
</div>
{access?.policyId !== undefined && access?.policyId > 0 && (
<>
<h5 className="heading-without-wrap">Policy Details</h5>
<div className="wrap">
- <PolicyViewDetails paramsData={access} policyView={false} />
+ <PolicyViewDetails
+ paramsData={pick(access, [
+ "eventTime",
+ "policyId",
+ "policyVersion"
+ ])}
+ policyView={false}
+ />
</div>
</>
)}
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogModal.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogModal.jsx
new file mode 100644
index 0000000..c42daad
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogModal.jsx
@@ -0,0 +1,56 @@
+/*
+ * 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 from "react";
+import { Button, Modal } from "react-bootstrap";
+import { Link } from "react-router-dom";
+import AccessLogTable from "./AccessLogTable";
+
+export const AccessLogModal = (props) => {
+ return (
+ <Modal show={props.showRowModal} size="lg" onHide={props.hideRowModal}>
+ <Modal.Header closeButton>
+ <Modal.Title>
+ <h4>
+ Audit Access Log Detail
+ <Link
+ className="text-info"
+ target="_blank"
+ title="Show log details in next tab"
+ to={{
+ pathname: `/reports/audit/eventlog/${props.rowData.eventId}`
+ }}
+ >
+ <i className="fa-fw fa fa-external-link float-end text-info"></i>
+ </Link>
+ </h4>
+ </Modal.Title>
+ </Modal.Header>
+ <Modal.Body className="overflow-auto p-3 mb-3 mb-md-0 me-md-3">
+ <AccessLogTable data={props.rowData}></AccessLogTable>
+ </Modal.Body>
+ <Modal.Footer>
+ <Button variant="primary" size="sm" onClick={props.hideRowModal}>
+ OK
+ </Button>
+ </Modal.Footer>
+ </Modal>
+ );
+};
+export default AccessLogModal;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogPolicyModal.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogPolicyModal.jsx
new file mode 100644
index 0000000..1c075b8
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogPolicyModal.jsx
@@ -0,0 +1,193 @@
+/*
+ * 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 { fetchApi } from "Utils/fetchAPI";
+import { indexOf, isUndefined } from "lodash";
+import React, { useEffect, useState } from "react";
+import { Button, Modal } from "react-bootstrap";
+import { PolicyViewDetails } from "Views/AuditEvent/Admin/AdminLogs/PolicyViewDetails";
+
+export const AccessLogPolicyModal = (props) => {
+ const [policyData, setPolicyData] = useState(null);
+ const [policyVersionList, setPolicyVersion] = useState([]);
+
+ useEffect(() => {
+ if (props.showPolicyModal) {
+ setPolicyData(props.policyData);
+ fetchPolicyVersion(props.policyData.policyId);
+ }
+ }, [props.showPolicyModal]);
+
+ const hidePolicyModal = () => {
+ setPolicyData(null);
+ setPolicyVersion([]);
+ props.hidePolicyModal();
+ };
+
+ const refreshTable = () => {
+ setPolicyData(null);
+ setPolicyVersion([]);
+ props.hidePolicyModal();
+ props.refreshTable();
+ };
+
+ const fetchPolicyVersion = async (policyId) => {
+ let versionsResp = {};
+
+ try {
+ versionsResp = await fetchApi({
+ url: `plugins/policy/${policyId}/versionList`
+ });
+ } catch (error) {
+ console.error(`Error occurred while fetching policy version : ${error}`);
+ }
+
+ setPolicyVersion(
+ versionsResp.data.value
+ .split(",")
+ .map(Number)
+ .sort(function (a, b) {
+ return a - b;
+ })
+ );
+ };
+
+ const getUpdatedPolicyData = (e) => {
+ e.preventDefault();
+
+ let updatedPolicyData = {};
+ let policyVersion = 1;
+
+ if (e.currentTarget.classList.contains("active")) {
+ let currentPolicyVersion = policyData && policyData.policyVersion;
+ let currentPolicyVersionList = policyVersionList;
+
+ if (e.currentTarget.title == "previous") {
+ policyVersion =
+ currentPolicyVersionList[
+ (indexOf(currentPolicyVersionList, currentPolicyVersion) - 1) %
+ currentPolicyVersionList.length
+ ];
+ } else {
+ policyVersion =
+ currentPolicyVersionList[
+ (indexOf(currentPolicyVersionList, currentPolicyVersion) + 1) %
+ currentPolicyVersionList.length
+ ];
+ }
+ }
+
+ updatedPolicyData.policyVersion = policyVersion;
+ updatedPolicyData.policyId = policyData.policyId;
+ updatedPolicyData.isChangeVersion = true;
+ setPolicyData(updatedPolicyData);
+ };
+
+ const getRevertedPolicyData = (e) => {
+ e.preventDefault();
+
+ let revertPolicyData = {};
+ let policyVersion = policyData && policyData.policyVersion;
+
+ revertPolicyData.policyVersion = policyVersion;
+ revertPolicyData.policyId = policyData.policyId;
+ revertPolicyData.isRevert = true;
+ setPolicyData(revertPolicyData);
+ };
+
+ return (
+ <Modal show={props.showPolicyModal} onHide={hidePolicyModal} size="xl">
+ <Modal.Header closeButton>
+ <Modal.Title>Policy Details</Modal.Title>
+ </Modal.Header>
+ {policyData !== null && (
+ <React.Fragment>
+ <Modal.Body>
+ <PolicyViewDetails
+ paramsData={policyData}
+ policyView={props.policyView}
+ refreshTable={refreshTable}
+ />
+ </Modal.Body>
+ <Modal.Footer>
+ <div className="policy-version">
+ <span>
+ <i
+ className={
+ policyData && policyData.policyVersion > 1
+ ? "fa-fw fa fa-chevron-left active"
+ : "fa-fw fa fa-chevron-left"
+ }
+ title="previous"
+ onClick={(e) =>
+ e.currentTarget.classList.contains("active") &&
+ getUpdatedPolicyData(e)
+ }
+ ></i>
+ <span>{`Version ${
+ policyData && policyData.policyVersion
+ }`}</span>
+ <i
+ className={
+ !isUndefined(
+ policyVersionList[
+ indexOf(
+ policyVersionList,
+ policyData && policyData.policyVersion
+ ) + 1
+ ]
+ )
+ ? "fa-fw fa fa-chevron-right active"
+ : "fa-fw fa fa-chevron-right"
+ }
+ title="next"
+ onClick={(e) =>
+ e.currentTarget.classList.contains("active") &&
+ getUpdatedPolicyData(e)
+ }
+ ></i>
+ </span>
+ {props.policyRevert &&
+ !isUndefined(
+ policyVersionList[
+ indexOf(
+ policyVersionList,
+ policyData && policyData.policyVersion
+ ) + 1
+ ]
+ ) && (
+ <Button
+ variant="primary"
+ size="sm"
+ onClick={(e) => getRevertedPolicyData(e)}
+ >
+ Revert
+ </Button>
+ )}
+ </div>
+ <Button variant="primary" size="sm" onClick={hidePolicyModal}>
+ OK
+ </Button>
+ </Modal.Footer>
+ </React.Fragment>
+ )}
+ </Modal>
+ );
+};
+export default AccessLogPolicyModal;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogsTable.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogTable.jsx
similarity index 96%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogsTable.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogTable.jsx
index 753a23d..32b127f 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogsTable.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogTable.jsx
@@ -25,10 +25,10 @@
import {
ServiceRequestDataRangerAcl,
ServiceRequestDataHadoopAcl
-} from "../../utils/XAEnums";
-import { requestDataTitle } from "../../utils/XAUtils";
+} from "Utils/XAEnums";
+import { requestDataTitle } from "Utils/XAUtils";
-export const AccessLogsTable = ({ data = {} }) => {
+export const AccessLogTable = ({ data = {} }) => {
const {
eventTime,
eventId,
@@ -57,7 +57,7 @@
} = data;
const copyText = (val) => {
- !isEmpty(val) && toast.success("Copied successfully!!");
+ !isEmpty(val) && toast.success("Copied successfully !!");
return val;
};
@@ -235,4 +235,4 @@
</Table>
);
};
-export default AccessLogsTable;
+export default AccessLogTable;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogs.jsx
similarity index 67%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogs.jsx
index 858de6c..0bf301c 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AccessLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Access/AccessLogs.jsx
@@ -17,24 +17,31 @@
* under the License.
*/
-import React, { useState, useCallback, useEffect, useRef } from "react";
-import { useSearchParams, useOutletContext, Link } from "react-router-dom";
-import { Badge, Button, Row, Col, Table, Modal } from "react-bootstrap";
+import React, { useState, useCallback, useEffect, useReducer } from "react";
+import {
+ useSearchParams,
+ useOutletContext,
+ useLocation
+} from "react-router-dom";
+import { Badge, Row, Col, Table } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
import dateFormat from "dateformat";
import { fetchApi } from "Utils/fetchAPI";
import {
+ AccessMoreLess,
AuditFilterEntries,
+ CustomTooltip,
CustomPopoverOnClick,
- CustomPopoverTagOnClick
+ CustomPopoverTagOnClick,
+ Loader
} from "Components/CommonComponents";
import moment from "moment-timezone";
-import AccessLogsTable from "./AccessLogsTable";
+import AccessLogModal from "./AccessLogModal";
+import AccessLogPolicyModal from "./AccessLogPolicyModal";
import {
isEmpty,
isUndefined,
pick,
- indexOf,
map,
sortBy,
toString,
@@ -47,9 +54,7 @@
} from "lodash";
import { toast } from "react-toastify";
import qs from "qs";
-import { AccessMoreLess } from "Components/CommonComponents";
-import { PolicyViewDetails } from "./AdminLogs/PolicyViewDetails";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import {
isKeyAdmin,
isKMSAuditor,
@@ -59,165 +64,145 @@
requestDataTitle,
fetchSearchFilterParams,
parseSearchFilter
-} from "../../utils/XAUtils";
-import { CustomTooltip, Loader } from "../../components/CommonComponents";
+} from "Utils/XAUtils";
import {
ServiceRequestDataRangerAcl,
ServiceRequestDataHadoopAcl
-} from "../../utils/XAEnums";
-import { getServiceDef } from "../../utils/appState";
+} from "Utils/XAEnums";
+import { getServiceDef } from "Utils/appState";
+import { ACTIONS } from "Views/AuditEvent/action";
+import { reducer, ACCESS_INITIAL_STATE } from "Views/AuditEvent/reducer";
-function Access() {
- const context = useOutletContext();
- const services = context.services;
- const servicesAvailable = context.servicesAvailable;
- const isKMSRole = isKeyAdmin() || isKMSAuditor();
- const [searchParams, setSearchParams] = useSearchParams();
- const [accessListingData, setAccessLogs] = useState([]);
- const [zones, setZones] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageCount, setPageCount] = React.useState(0);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [entries, setEntries] = useState([]);
- const [showrowmodal, setShowRowModal] = useState(false);
- const [policyviewmodal, setPolicyViewModal] = useState(false);
- const [policyParamsData, setPolicyParamsData] = useState(null);
- const [rowdata, setRowData] = useState([]);
- const [checked, setChecked] = useState(() => {
- let urlParam = Object.fromEntries([...searchParams]);
- if (urlParam?.excludeServiceUser) {
- return urlParam.excludeServiceUser == "true" ? true : false;
- } else {
- return localStorage?.excludeServiceUser == "true" ? true : false;
- }
- });
- const [currentPage, setCurrentPage] = useState(1);
- const fetchIdRef = useRef(0);
- const [contentLoader, setContentLoader] = useState(true);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [resetPage, setResetpage] = useState({ page: 0 });
- const [policyDetails, setPolicyDetails] = useState({});
+function AccessLogs() {
+ const [state, dispatch] = useReducer(reducer, ACCESS_INITIAL_STATE);
+
+ const location = useLocation();
+
+ const { services, servicesAvailable } = useOutletContext();
+
const { allServiceDefs } = cloneDeep(getServiceDef());
+ const isKMSRole = isKeyAdmin() || isKMSAuditor();
+
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const [excludeServiceUser, setExcludeServiceUser] = useState(() => {
+ return localStorage?.excludeServiceUser === "true" ? true : false;
+ });
useEffect(() => {
if (!isKMSRole) {
- fetchZones();
+ fetchSecurityZones();
}
- let currentDate = moment(moment()).format("MM/DD/YYYY");
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const currentDate = moment(moment()).format("MM/DD/YYYY");
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams("bigData", searchParams, searchFilterOptions);
if (
!has(searchFilterParam, "startDate") &&
!has(searchFilterParam, "endDate")
) {
- searchParam["startDate"] = currentDate;
- searchFilterParam["startDate"] = currentDate;
+ searchParam.startDate = currentDate;
+ searchFilterParam.startDate = currentDate;
defaultSearchFilterParam.push({
category: "startDate",
value: currentDate
});
}
- // Add excludeServiceUser if not present in the search param with default state value of checked
- if (!has(searchParam, "excludeServiceUser")) {
- searchParam["excludeServiceUser"] = checked;
- }
- localStorage.setItem("excludeServiceUser", checked);
-
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
- setSearchFilterParams(searchFilterParam);
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("bigData", JSON.stringify(searchParam));
}, []);
useEffect(() => {
if (servicesAvailable !== null) {
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams("bigData", searchParams, searchFilterOptions);
- // Update excludeServiceUser in the search param and in the localStorage
- if (searchParam?.excludeServiceUser) {
- setChecked(searchParam?.excludeServiceUser == "true" ? true : false);
- localStorage.setItem(
- "excludeServiceUser",
- searchParam?.excludeServiceUser
- );
- }
-
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("bigData", JSON.stringify(searchParam));
-
- setContentLoader(false);
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
}
- }, [searchParams, servicesAvailable]);
+ }, [location.search, servicesAvailable]);
const fetchAccessLogsInfo = useCallback(
async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
- setLoader(true);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
if (servicesAvailable !== null) {
- let logsResp = [];
- let logs = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- if (Object.fromEntries([...searchParams])?.excludeServiceUser) {
- params["excludeServiceUser"] =
- Object.fromEntries([...searchParams])?.excludeServiceUser ==
- "true"
- ? true
- : false;
- } else {
- params["excludeServiceUser"] = checked;
- }
- if (sortBy.length > 0) {
- params["sortBy"] = getTableSortBy(sortBy);
- params["sortType"] = getTableSortType(sortBy);
- }
- try {
- logsResp = await fetchApi({
- url: "assets/accessAudit",
- params: params,
- skipNavigate: true,
- paramsSerializer: function (params) {
- return qs.stringify(params, { arrayFormat: "repeat" });
- }
- });
- logs = logsResp.data.vXAccessAudits;
- totalCount = logsResp.data.totalCount;
- } catch (error) {
- serverError(error);
- console.error(
- `Error occurred while fetching Access logs! ${error}`
- );
- }
- setAccessLogs(logs);
- setEntries(logsResp.data);
- setPageCount(Math.ceil(totalCount / pageSize));
- setResetpage({ page: gotoPage });
- setLoader(false);
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize,
+ excludeServiceUser: excludeServiceUser,
+ ...(sortBy.length > 0 && {
+ sortBy: getTableSortBy(sortBy),
+ sortType: getTableSortType(sortBy)
+ })
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "assets/accessAudit",
+ params: params,
+ skipNavigate: true,
+ paramsSerializer: function (params) {
+ return qs.stringify(params, { arrayFormat: "repeat" });
+ }
+ });
+
+ const logsEntries = pick(response.data, [
+ "startIndex",
+ "pageSize",
+ "totalCount",
+ "resultSize"
+ ]);
+ const logsResp = response.data?.vXAccessAudits || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: logsResp,
+ entries: logsEntries,
+ pageCount: Math.ceil(totalCount / pageSize),
+ resetPage: { page: gotoPage }
+ });
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching access logs : ${error}`);
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
}
},
- [updateTable, checked, searchFilterParams, servicesAvailable]
+ [state.refreshTableData, excludeServiceUser, servicesAvailable]
);
- const fetchZones = async () => {
+ const fetchSecurityZones = async () => {
let zonesResp = [];
try {
const response = await fetchApi({
@@ -226,14 +211,17 @@
zonesResp = response?.data || [];
} catch (error) {
- console.error(`Error occurred while fetching Zones! ${error}`);
+ console.error(`Error occurred while fetching security zones : ${error}`);
}
- setZones(sortBy(zonesResp, ["name"]));
+ dispatch({
+ type: ACTIONS.SET_SECURITY_ZONES,
+ securityZones: sortBy(zonesResp, ["name"])
+ });
};
- const toggleChange = (chkVal) => {
- let checkBoxValue = chkVal?.target?.checked;
+ const toggleChange = (e) => {
+ let checkboxValue = e?.target?.checked;
let searchParam = {};
for (const [key, value] of searchParams.entries()) {
@@ -262,67 +250,54 @@
}
}
- searchParam["excludeServiceUser"] = checkBoxValue;
- localStorage.setItem("excludeServiceUser", checkBoxValue);
+ localStorage.setItem("excludeServiceUser", checkboxValue);
- setSearchParams(searchParam, { replace: true });
- setAccessLogs([]);
- setChecked(chkVal?.target?.checked);
- setLoader(true);
- setUpdateTable(moment.now());
+ setExcludeServiceUser(checkboxValue);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
};
- const handleClosePolicyId = () => setPolicyViewModal(false);
- const handleClose = () => setShowRowModal(false);
+ const hidePolicyModal = () =>
+ dispatch({
+ type: ACTIONS.SHOW_POLICY_MODAL,
+ showPolicyModal: false,
+ policyData: null
+ });
- const rowModal = (row) => {
- setShowRowModal(true);
- setRowData(row.original);
+ const hideRowModal = () =>
+ dispatch({
+ type: ACTIONS.SHOW_ROW_MODAL,
+ showRowModal: false,
+ rowData: {}
+ });
+
+ const openRowModal = (row) => {
+ dispatch({
+ type: ACTIONS.SHOW_ROW_MODAL,
+ showRowModal: true,
+ rowData: row.original
+ });
};
- const openModal = (policyDetails) => {
- let policyParams = pick(policyDetails, [
- "eventTime",
- "policyId",
- "policyVersion"
- ]);
- setPolicyViewModal(true);
- setPolicyDetails(policyDetails);
- setPolicyParamsData(policyParams);
- fetchVersions(policyDetails.policyId);
- };
-
- const fetchVersions = async (policyId) => {
- let versionsResp = {};
- try {
- versionsResp = await fetchApi({
- url: `plugins/policy/${policyId}/versionList`
- });
- } catch (error) {
- console.error(
- `Error occurred while fetching Policy Version or CSRF headers! ${error}`
- );
- }
- setCurrentPage(
- versionsResp.data.value
- .split(",")
- .map(Number)
- .sort(function (a, b) {
- return a - b;
- })
- );
- setLoader(false);
+ const openPolicyModal = (policy) => {
+ let policyParams = pick(policy, ["eventTime", "policyId", "policyVersion"]);
+ dispatch({
+ type: ACTIONS.SHOW_POLICY_MODAL,
+ showPolicyModal: true,
+ policyData: policyParams
+ });
};
const refreshTable = () => {
- setAccessLogs([]);
- setLoader(true);
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
};
const requestDataContent = (requestData) => {
const copyText = (val) => {
- !isEmpty(val) && toast.success("Copied successfully!!");
+ !isEmpty(val) && toast.success("Copied successfully !!");
return val;
};
return (
@@ -347,7 +322,7 @@
);
};
- const rsrcTagContent = (requestData) => {
+ const requestTagContent = (requestData) => {
return (
<>
<Table bordered hover>
@@ -407,38 +382,6 @@
);
};
- const previousVersion = (e) => {
- if (e.currentTarget.classList.contains("active")) {
- let curr = policyParamsData && policyParamsData.policyVersion;
- let policyVersionList = currentPage;
- var previousVal =
- policyVersionList[
- (indexOf(policyVersionList, curr) - 1) % policyVersionList.length
- ];
- }
- let prevVal = {};
- prevVal.policyVersion = previousVal;
- prevVal.policyId = policyParamsData.policyId;
- prevVal.isChangeVersion = true;
- setPolicyParamsData(prevVal);
- };
-
- const nextVersion = (e) => {
- if (e.currentTarget.classList.contains("active")) {
- let curr = policyParamsData && policyParamsData.policyVersion;
- let policyVersionList = currentPage;
- var nextValue =
- policyVersionList[
- (indexOf(policyVersionList, curr) + 1) % policyVersionList.length
- ];
- }
- let nextVal = {};
- nextVal.policyVersion = nextValue;
- nextVal.policyId = policyParamsData.policyId;
- nextVal.isChangeVersion = true;
- setPolicyParamsData(nextVal);
- };
-
const columns = React.useMemo(
() => [
{
@@ -455,7 +398,7 @@
className="text-primary"
onClick={(e) => {
e.stopPropagation();
- openModal(rawValue.row.original);
+ openPolicyModal(rawValue.row.original);
}}
>
{rawValue.value}
@@ -666,7 +609,7 @@
{rawValue.value}
</div>
);
- } else return "--";
+ } else return <div className="text-center">--</div>;
},
width: 150,
disableResizing: true,
@@ -742,16 +685,16 @@
Header: "Tags",
accessor: "tags",
Cell: (rawValue) => {
- let Tags = [];
+ let tags = [];
if (!isEmpty(rawValue.value)) {
- Tags = sortBy(JSON.parse(rawValue.value), "type")?.map((tag) => {
+ tags = sortBy(JSON.parse(rawValue.value), "type")?.map((tag) => {
if (tag.attributes && !isEmpty(tag.attributes)) {
return (
<CustomPopoverTagOnClick
icon="text-info"
data={tag.type}
title={"Atrribute Details"}
- content={rsrcTagContent(tag.attributes)}
+ content={requestTagContent(tag.attributes)}
placement="left"
trigger={["click", "focus"]}
></CustomPopoverTagOnClick>
@@ -763,7 +706,7 @@
} else {
return <div className="text-center">--</div>;
}
- return <AccessMoreLess Data={Tags} />;
+ return <AccessMoreLess Data={tags} />;
},
width: 140,
disableResizing: true,
@@ -844,10 +787,10 @@
}));
};
- const getZones = () => {
+ const getSecurityZones = () => {
let zonesName = [];
- zonesName = map(zones, function (zone) {
+ zonesName = map(state.securityZones, function (zone) {
return { label: zone.name, value: zone.name };
});
@@ -855,19 +798,22 @@
};
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- searchParam["excludeServiceUser"] = checked;
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
- setSearchFilterParams(searchFilterParam);
setSearchParams(searchParam, { replace: true });
localStorage.setItem("bigData", JSON.stringify(searchParam));
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
@@ -1008,7 +954,7 @@
label: "Zone Name",
urlLabel: "zoneName",
type: "textoptions",
- options: getZones
+ options: getSecurityZones
},
{
category: "excludeResourceName",
@@ -1018,7 +964,7 @@
}
];
- return contentLoader ? (
+ return state.contentLoader ? (
<Loader />
) : (
<div className="wrap">
@@ -1031,7 +977,7 @@
placeholder="Search for your access audits..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
<span className="info-icon">
@@ -1078,6 +1024,7 @@
</div>
</Col>
</Row>
+
<div className="position-relative">
<Row className="mb-2">
<Col sm={2}>
@@ -1085,7 +1032,7 @@
<input
type="checkbox"
className="align-middle"
- checked={checked}
+ checked={excludeServiceUser}
onChange={toggleChange}
data-id="serviceUsersExclude"
data-cy="serviceUsersExclude"
@@ -1093,22 +1040,23 @@
</Col>
<Col sm={9}>
<AuditFilterEntries
- entries={entries}
+ entries={state.entries}
refreshTable={refreshTable}
/>
</Col>
</Row>
+
<XATableLayout
- data={accessListingData}
+ data={state.tableListingData}
columns={columns}
fetchData={fetchAccessLogsInfo}
- totalCount={entries && entries.totalCount}
- loading={loader}
- pageCount={pageCount}
+ totalCount={state.entries && state.entries.totalCount}
+ loading={state.loader}
+ pageCount={state.pageCount}
getRowProps={(row) => ({
onClick: (e) => {
e.stopPropagation();
- rowModal(row);
+ openRowModal(row);
}
})}
columnHide={{ tableName: "bigData", isVisible: true }}
@@ -1117,85 +1065,23 @@
defaultSort={getDefaultSort}
/>
</div>
- <Modal show={showrowmodal} size="lg" onHide={handleClose}>
- <Modal.Header closeButton>
- <Modal.Title>
- <h4>
- Audit Access Log Detail
- <Link
- className="text-info"
- target="_blank"
- title="Show log details in next tab"
- to={{
- pathname: `/reports/audit/eventlog/${rowdata.eventId}`
- }}
- >
- <i className="fa-fw fa fa-external-link float-end text-info"></i>
- </Link>
- </h4>
- </Modal.Title>
- </Modal.Header>
- <Modal.Body className="overflow-auto p-3 mb-3 mb-md-0 me-md-3">
- <AccessLogsTable data={rowdata}></AccessLogsTable>
- </Modal.Body>
- <Modal.Footer>
- <Button variant="primary" onClick={handleClose}>
- OK
- </Button>
- </Modal.Footer>
- </Modal>
- <Modal show={policyviewmodal} onHide={handleClosePolicyId} size="xl">
- <Modal.Header closeButton>
- <Modal.Title>Policy Details</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- <PolicyViewDetails
- paramsData={policyParamsData}
- policyView={false}
- />
- </Modal.Body>
- <Modal.Footer>
- <div className="policy-version pull-left">
- <i
- className={
- policyParamsData && policyParamsData.policyVersion > 1
- ? "fa-fw fa fa-chevron-left active"
- : "fa-fw fa fa-chevron-left"
- }
- onClick={(e) =>
- e.currentTarget.classList.contains("active") &&
- previousVersion(e)
- }
- ></i>
- <span>{`Version ${
- policyParamsData && policyParamsData.policyVersion
- }`}</span>
- <i
- className={
- !isUndefined(
- currentPage[
- indexOf(
- currentPage,
- policyParamsData && policyParamsData.policyVersion
- ) + 1
- ]
- )
- ? "fa-fw fa fa-chevron-right active"
- : "fa-fw fa fa-chevron-right"
- }
- onClick={(e) =>
- e.currentTarget.classList.contains("active") && nextVersion(e)
- }
- ></i>
- </div>
- <Button variant="primary" onClick={handleClosePolicyId}>
- OK
- </Button>
- </Modal.Footer>
- </Modal>
+
+ <AccessLogModal
+ rowData={state.rowData}
+ showRowModal={state.showRowModal}
+ hideRowModal={hideRowModal}
+ ></AccessLogModal>
+
+ <AccessLogPolicyModal
+ policyData={state.policyData}
+ policyView={false}
+ policyRevert={false}
+ showPolicyModal={state.showPolicyModal}
+ hidePolicyModal={hidePolicyModal}
+ ></AccessLogPolicyModal>
</React.Fragment>
</div>
);
}
-export default Access;
+export default AccessLogs;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs.jsx
similarity index 76%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs.jsx
index ed1ff8b..ad54c45 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs.jsx
@@ -17,19 +17,19 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
-import { useSearchParams, useNavigate } from "react-router-dom";
+import React, { useCallback, useEffect, useReducer } from "react";
+import { useSearchParams, useNavigate, useLocation } from "react-router-dom";
import { Badge, Row, Col } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
import { fetchApi } from "Utils/fetchAPI";
-import { ClassTypes, enumValueToLabel } from "../../utils/XAEnums";
+import { ClassTypes, enumValueToLabel } from "Utils/XAEnums";
import dateFormat from "dateformat";
import AdminModal from "./AdminModal";
-import { AuditFilterEntries } from "Components/CommonComponents";
import OperationAdminModal from "./OperationAdminModal";
+import { AuditFilterEntries, Loader } from "Components/CommonComponents";
import moment from "moment-timezone";
-import { capitalize, startCase, sortBy, toLower } from "lodash";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
+import { capitalize, startCase, sortBy, toLower, pick } from "lodash";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import {
getTableSortBy,
getTableSortType,
@@ -37,105 +37,131 @@
parseSearchFilter,
serverError,
currentTimeZone
-} from "../../utils/XAUtils";
-import { Loader } from "../../components/CommonComponents";
+} from "Utils/XAUtils";
+import { ACTIONS } from "Views/AuditEvent/action";
+import { reducer, ADMIN_INITIAL_STATE } from "Views/AuditEvent/reducer";
-function Admin() {
- const [adminListingData, setAdminLogs] = useState([]);
- const [sessionId, setSessionId] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageCount, setPageCount] = useState(0);
- const [showmodal, setShowModal] = useState(false);
- const [entries, setEntries] = useState([]);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [showrowmodal, setShowRowModal] = useState(false);
- const [rowdata, setRowData] = useState([]);
- const fetchIdRef = useRef(0);
- const [contentLoader, setContentLoader] = useState(true);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [resetPage, setResetpage] = useState({ page: null });
- const handleClose = () => setShowModal(false);
- const handleClosed = () => setShowRowModal(false);
+function AdminLogs() {
+ const [state, dispatch] = useReducer(reducer, ADMIN_INITIAL_STATE);
+
+ const location = useLocation();
const navigate = useNavigate();
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const hideRowModal = () =>
+ dispatch({
+ type: ACTIONS.SHOW_ROW_MODAL,
+ showRowModal: false,
+ rowData: {}
+ });
+
+ const hideSessionModal = () =>
+ dispatch({
+ type: ACTIONS.SHOW_SESSION_MODAL,
+ showSessionModal: false,
+ sessionId: undefined
+ });
+
+ const openRowModal = async (row) => {
+ const { original = {} } = row;
+
+ dispatch({
+ type: ACTIONS.SHOW_ROW_MODAL,
+ showRowModal: true,
+ rowData: original
+ });
+ };
+
+ const openSessionModal = (sessionId) => {
+ dispatch({
+ type: ACTIONS.SHOW_SESSION_MODAL,
+ showSessionModal: true,
+ sessionId: sessionId
+ });
+ };
+
const updateSessionId = (id) => {
navigate(`/reports/audit/admin?sessionId=${id}`);
setSearchParams({ sessionId: id }, { replace: true });
- setContentLoader(true);
- };
-
- const rowModal = async (row) => {
- const { original = {} } = row;
- original.objectId;
- setShowRowModal(true);
- setRowData(original);
};
useEffect(() => {
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams("admin", searchParams, searchFilterOptions);
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("admin", JSON.stringify(searchParam));
- setContentLoader(false);
- }, [searchParams]);
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ }, [location.search]);
const fetchAdminLogsInfo = useCallback(
async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
- setLoader(true);
- let logsResp = [];
- let adminlogs = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- if (sortBy.length > 0) {
- params["sortBy"] = getTableSortBy(sortBy);
- params["sortType"] = getTableSortType(sortBy);
- }
- try {
- logsResp = await fetchApi({
- url: "assets/report",
- params: params
- });
- adminlogs = logsResp.data.vXTrxLogs;
- totalCount = logsResp.data.totalCount;
- } catch (error) {
- serverError(error);
- console.error(`Error occurred while fetching Admin logs! ${error}`);
- }
- setAdminLogs(adminlogs);
- setEntries(logsResp.data);
- setPageCount(Math.ceil(totalCount / pageSize));
- setResetpage({ page: gotoPage });
- setLoader(false);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize,
+ ...(sortBy.length > 0 && {
+ sortBy: getTableSortBy(sortBy),
+ sortType: getTableSortType(sortBy)
+ })
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "assets/report",
+ params: params
+ });
+
+ const logsEntries = pick(response.data, [
+ "startIndex",
+ "pageSize",
+ "totalCount",
+ "resultSize"
+ ]);
+ const logsResp = response.data?.vXTrxLogs || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: logsResp,
+ entries: logsEntries,
+ pageCount: Math.ceil(totalCount / pageSize),
+ resetPage: { page: gotoPage }
+ });
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching Admin logs! ${error}`);
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
const refreshTable = () => {
- setAdminLogs([]);
- setLoader(true);
- setUpdateTable(moment.now());
- };
-
- const openModal = (sessionId) => {
- setShowModal(true);
- setSessionId(sessionId);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
};
const columns = React.useMemo(
@@ -380,7 +406,7 @@
className="text-primary"
onClick={(e) => {
e.stopPropagation();
- openModal(sessionId);
+ openSessionModal(sessionId);
}}
data-id={sessionId}
data-cy={sessionId}
@@ -411,17 +437,22 @@
);
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
localStorage.setItem("admin", JSON.stringify(searchParam));
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
@@ -496,7 +527,7 @@
}
];
- return contentLoader ? (
+ return state.contentLoader ? (
<Loader />
) : (
<div className="wrap">
@@ -509,43 +540,49 @@
placeholder="Search for your access logs..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</div>
</Col>
</Row>
- <AuditFilterEntries entries={entries} refreshTable={refreshTable} />
+ <AuditFilterEntries
+ entries={state.entries}
+ refreshTable={refreshTable}
+ />
<XATableLayout
- data={adminListingData}
+ data={state.tableListingData}
columns={columns}
fetchData={fetchAdminLogsInfo}
- totalCount={entries && entries.totalCount}
- pageCount={pageCount}
- loading={loader}
+ totalCount={state.entries && state.entries.totalCount}
+ pageCount={state.pageCount}
+ loading={state.loader}
columnSort={true}
defaultSort={getDefaultSort}
getRowProps={(row) => ({
- onClick: () => rowModal(row)
+ onClick: (e) => {
+ e.stopPropagation();
+ openRowModal(row);
+ }
})}
/>
<AdminModal
- show={showmodal}
- data={sessionId}
- onHide={handleClose}
+ show={state.showSessionModal}
+ data={state.sessionId}
+ onHide={hideSessionModal}
updateSessionId={updateSessionId}
></AdminModal>
<OperationAdminModal
- show={showrowmodal}
- data={rowdata}
- onHide={handleClosed}
+ data={state.rowData}
+ show={state.showRowModal}
+ onHide={hideRowModal}
></OperationAdminModal>
</React.Fragment>
</div>
);
}
-export default Admin;
+export default AdminLogs;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DataShareInDatasetLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DataShareInDatasetLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DataShareInDatasetLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DataShareInDatasetLogs.jsx
index 05d505d..ab6a63e 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DataShareInDatasetLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DataShareInDatasetLogs.jsx
@@ -20,7 +20,7 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
export const DataShareInDatasetLogs = ({ data, reportdata }) => {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DataShareLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DataShareLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DataShareLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DataShareLogs.jsx
index f4b7ff7..6cfcb4b 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DataShareLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DataShareLogs.jsx
@@ -20,7 +20,7 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
export const DataShareLogs = ({ data, reportdata }) => {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DatasetInProjectLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DatasetInProjectLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DatasetInProjectLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DatasetInProjectLogs.jsx
index f78cfe4..1c9e3d2 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DatasetInProjectLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DatasetInProjectLogs.jsx
@@ -20,7 +20,7 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
export const DatasetInProjectLogs = ({ data, reportdata }) => {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DatasetLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DatasetLogs.jsx
similarity index 98%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DatasetLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DatasetLogs.jsx
index d7c8e00..d0a3b22 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/DatasetLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/DatasetLogs.jsx
@@ -20,7 +20,7 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
export const DatasetLogs = ({ data, reportdata }) => {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/GroupLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/GroupLogs.jsx
similarity index 98%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/GroupLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/GroupLogs.jsx
index 0d9b98d..0410625 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/GroupLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/GroupLogs.jsx
@@ -19,9 +19,9 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { currentTimeZone } from "Utils/XAUtils";
export const GroupLogs = ({ data, reportdata }) => {
const { objectName, objectClassType, createDate, owner, action } = data;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PasswordLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PasswordLogs.jsx
similarity index 95%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PasswordLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PasswordLogs.jsx
index cd4f7bd..a0c5d27 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PasswordLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PasswordLogs.jsx
@@ -19,8 +19,8 @@
import React from "react";
import { Table } from "react-bootstrap";
-import { ClassTypes } from "../../../utils/XAEnums";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { ClassTypes } from "Utils/XAEnums";
+import { currentTimeZone } from "Utils/XAUtils";
export const PasswordLogs = ({ data, reportdata }) => {
const { objectName, objectClassType, createDate, owner, action } = data;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyLogs.jsx
index 8d5df0c..ec717b7 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyLogs.jsx
@@ -424,7 +424,7 @@
if (
JSON.stringify(Object.keys(oldVal)) == JSON.stringify(Object.keys(newVal))
) {
- Object.keys(oldVal)?.map((key, index) => {
+ Object.keys(oldVal)?.map((key) => {
return tablerow.push(
<>
{!isEqual(oldVal[key]?.values, newVal[key]?.values) && (
@@ -497,7 +497,7 @@
JSON.stringify(Object.keys(oldVal)) !==
JSON.stringify(Object.keys(newVal))
) {
- Object.keys(newVal)?.map((key, index) => {
+ Object.keys(newVal)?.map((key) => {
return tablerow.push(
<>
{!isEqual(newVal[key]?.values, oldVal[key]?.values) && (
@@ -549,7 +549,7 @@
);
});
- Object.keys(oldVal)?.map((key, index) => {
+ Object.keys(oldVal)?.map((key) => {
return tablerow.push(
<>
{!isEqual(oldVal[key]?.values, newVal[key]?.values) && (
@@ -1738,7 +1738,7 @@
keynew = !isEmpty(obj.previousValue) && JSON.parse(obj.previousValue);
});
- Object.keys(keynew).map((key, index) => {
+ Object.keys(keynew).map((key) => {
return tablerow.push(
<>
<tr>
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/Admin/AdminLogs/PolicyViewDetails.jsx
similarity index 94%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/PolicyViewDetails.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/PolicyViewDetails.jsx
index ac951e7..2c96e15 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/Admin/AdminLogs/PolicyViewDetails.jsx
@@ -20,28 +20,28 @@
import React, { useState, useEffect } from "react";
import { fetchApi } from "Utils/fetchAPI";
import { Table, Badge, Row, Col } from "react-bootstrap";
-import { RangerPolicyType, DefStatus } from "../../../utils/XAEnums";
+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 { ModalLoader } from "../../../components/CommonComponents";
-import { getServiceDef } from "../../../utils/appState";
+import { getResourcesDefVal, serverError } from "Utils/XAUtils";
+import { ModalLoader } from "Components/CommonComponents";
+import { getServiceDef } from "Utils/appState";
export function PolicyViewDetails(props) {
const isMultiResources = true;
const [access, setAccess] = useState([]);
- const [loader, SetLoader] = useState(true);
+ const [loader, setLoader] = useState(true);
const [serviceDef, setServiceDef] = useState({});
- const { updateServices } = props;
+
let { allServiceDefs, gdsServiceDef } = cloneDeep(getServiceDef());
useEffect(() => {
if (props.paramsData.isRevert) {
- fetchPolicyVersions();
+ revertPolicyVersion();
} else {
if (props.paramsData.isChangeVersion) {
- fetchByVersion();
+ fetchPolicyByVersion();
} else {
fetchInitialData();
}
@@ -53,30 +53,23 @@
]);
const fetchInitialData = async () => {
- await fetchByEventTime();
+ await fetchPolicyByEventTime();
};
- const fetchByEventTime = async () => {
+ const fetchPolicyByEventTime = async () => {
let accesslogs;
- let { policyView, paramsData } = props;
- let paramsVal = !policyView
- ? {
- eventTime: paramsData.eventTime,
- policyId: paramsData.policyId,
- versionNo: paramsData.policyVersion
- }
- : "";
+ let paramsVal = !props.policyView ? props.paramsData : "";
let accessLogsServiceDef;
try {
accesslogs = await fetchApi({
- url: policyView
- ? `plugins/policies/${paramsData.id}`
+ url: props.policyView
+ ? `plugins/policies/${props.paramsData.policyId}`
: "plugins/policies/eventTime",
params: paramsVal
});
} catch (error) {
- console.error(`eventTime can not be undefined ${error}`);
+ console.error(`Error occurred while fetching policy : ${error}`);
}
if (accesslogs?.data?.serviceType == "gds") {
@@ -89,40 +82,42 @@
setAccess(accesslogs?.data);
setServiceDef(accessLogsServiceDef);
- SetLoader(false);
+ setLoader(false);
};
- const fetchByVersion = async () => {
+ const fetchPolicyByVersion = async () => {
let accesslogs;
+
try {
accesslogs = await fetchApi({
- url: `plugins/policy/${
- props.paramsData.id || props.paramsData.policyId
- }/version/${props.paramsData.version || props.paramsData.policyVersion}`
+ url: `plugins/policy/${props.paramsData.policyId}/version/${props.paramsData.policyVersion}`
});
} catch (error) {
- console.error(`versionNo can not be undefined ${error}`);
+ console.error(
+ `Error occurred while fetching policy by version : ${error}`
+ );
}
+
setAccess(accesslogs?.data);
};
- const fetchPolicyVersions = async () => {
+ const revertPolicyVersion = async () => {
let accesslogs;
- let policyId = props.paramsData.id;
+ let policyId = props.paramsData.policyId;
+
try {
accesslogs = await fetchApi({
url: `plugins/policies/${policyId}`,
method: "PUT",
data: access
});
- updateServices();
toast.success("Policy reverted successfully");
+ props.refreshTable();
} catch (error) {
- console.error(
- `Error occurred while fetching Policy Version or CSRF headers! ${error}`
- );
+ console.error(`Error occurred while reverting policy : ${error}`);
serverError(error);
}
+
setAccess(accesslogs?.data);
};
@@ -155,7 +150,9 @@
zoneName,
additionalResources
} = access;
+
let additionalResourcesVal = [];
+
if (isMultiResources) {
additionalResourcesVal = [resources, ...(additionalResources || [])];
}
@@ -645,6 +642,7 @@
</p>
</div>
</div>
+
<p className="form-header">Policy Details :</p>
<div className="overflow-auto">
<Table bordered size="sm" className="table-audit-filter-ready-only">
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/ProjectLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/ProjectLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/ProjectLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/ProjectLogs.jsx
index 1e89484..a2a90af 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/ProjectLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/ProjectLogs.jsx
@@ -20,7 +20,7 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
export const ProjectLogs = ({ data, reportdata }) => {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/RoleLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/RoleLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/RoleLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/RoleLogs.jsx
index 09226da..cc49679 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/RoleLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/RoleLogs.jsx
@@ -19,9 +19,9 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { currentTimeZone } from "Utils/XAUtils";
export const RoleLogs = ({ data, reportdata }) => {
const { objectName, objectClassType, createDate, owner, action } = data;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/SecurityZonelogs.jsx
similarity index 98%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/SecurityZonelogs.jsx
index 92bc67f..5e9a864 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SecurityZonelogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/SecurityZonelogs.jsx
@@ -19,10 +19,9 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
-import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { currentTimeZone } from "Utils/XAUtils";
export const SecurityZonelogs = ({ data, reportdata }) => {
const { objectName, objectClassType, createDate, owner, action } = data;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/ServiceLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/ServiceLogs.jsx
similarity index 98%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/ServiceLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/ServiceLogs.jsx
index 3464880..d025f22 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/ServiceLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/ServiceLogs.jsx
@@ -19,9 +19,8 @@
import React from "react";
import { Badge, Table } from "react-bootstrap";
-import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { ClassTypes } from "Utils/XAEnums";
+import { currentTimeZone } from "Utils/XAUtils";
import { isEmpty, isUndefined, sortBy } from "lodash";
export const ServiceLogs = ({ data, reportdata }) => {
@@ -151,7 +150,7 @@
objectClassType == ClassTypes.CLASS_TYPE_RANGER_SERVICE.value && (
<div>
<div className="fw-bolder">Name: {objectName || ""}</div>
- <div className="fw-bolder">Date:{currentTimeZone(createDate)}</div>
+ <div className="fw-bolder">Date: {currentTimeZone(createDate)}</div>
<div className="fw-bolder">Created By: {owner}</div>
<br />
{action == "create" && (
@@ -249,7 +248,7 @@
<div className="col-md-6">
<div className="fw-bolder">Name : {objectName}</div>
<div className="fw-bolder">
- Date:{currentTimeZone(createDate)}
+ Date: {currentTimeZone(createDate)}
</div>
<div className="fw-bolder">Updated By: {owner}</div>
</div>
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SharedResourceLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/SharedResourceLogs.jsx
similarity index 99%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SharedResourceLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/SharedResourceLogs.jsx
index 4323ccc..c78847c 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/SharedResourceLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/SharedResourceLogs.jsx
@@ -20,7 +20,7 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
import dateFormat from "dateformat";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
export const SharedResourceLogs = ({ data, reportdata }) => {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserAssociationWithGroupLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserAssociationWithGroupLogs.jsx
similarity index 100%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserAssociationWithGroupLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserAssociationWithGroupLogs.jsx
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserLogs.jsx
similarity index 96%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserLogs.jsx
index 1fe2998..6afb381 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserLogs.jsx
@@ -19,9 +19,9 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
-import { ClassTypes, UserRoles } from "../../../utils/XAEnums";
+import { ClassTypes, UserRoles } from "Utils/XAEnums";
import { isEmpty, unionBy, difference, isEqual, without } from "lodash";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { currentTimeZone } from "Utils/XAUtils";
export const UserLogs = ({ data, reportdata }) => {
const { objectName, objectClassType, createDate, owner, action } = data;
@@ -168,11 +168,11 @@
})
)
: !isEmpty(filterdiff)
- ? filterdiff.map((obj) => obj).join(", ")
- : "--"
+ ? filterdiff.map((obj) => obj).join(", ")
+ : "--"
: !isEmpty(oldVals)
- ? oldVals.map((obj) => obj).join(", ")
- : "--"}
+ ? oldVals.map((obj) => obj).join(", ")
+ : "--"}
</>
);
};
@@ -205,11 +205,11 @@
})
)
: !isEmpty(filterdiff)
- ? filterdiff.map((obj) => obj).join(", ")
- : "--"
+ ? filterdiff.map((obj) => obj).join(", ")
+ : "--"
: !isEmpty(newVals)
- ? newVals.map((obj) => obj).join(", ")
- : "--"}
+ ? newVals.map((obj) => obj).join(", ")
+ : "--"}
</>
);
};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserprofileLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserprofileLogs.jsx
similarity index 97%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserprofileLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserprofileLogs.jsx
index f2bce89..4badff5 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminLogs/UserprofileLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminLogs/UserprofileLogs.jsx
@@ -19,9 +19,9 @@
import React from "react";
import { Table, Badge } from "react-bootstrap";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
import { isEmpty } from "lodash";
-import { currentTimeZone } from "../../../utils/XAUtils";
+import { currentTimeZone } from "Utils/XAUtils";
export const UserprofileLogs = ({ data, reportdata }) => {
const { objectName, objectClassType, createDate, owner, action } = data;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminModal.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminModal.jsx
new file mode 100644
index 0000000..c8eb63c
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/AdminModal.jsx
@@ -0,0 +1,178 @@
+/*
+ * 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, { useEffect, useState } from "react";
+import { useSearchParams } from "react-router-dom";
+import { fetchApi } from "Utils/fetchAPI";
+import { AuthStatus, AuthType } from "Utils/XAEnums";
+import { Modal, Table, Button } from "react-bootstrap";
+import { has, isEmpty } from "lodash";
+import { ModalLoader } from "Components/CommonComponents";
+import { currentTimeZone } from "Utils/XAUtils";
+
+export const AdminModal = (props) => {
+ const [authSession, setAuthSession] = useState([]);
+ const [loader, setLoader] = useState(true);
+ const [searchParams] = useSearchParams();
+
+ useEffect(() => {
+ if (props.show) {
+ handleShow();
+ }
+ }, [props.show]);
+
+ const hideSessionModal = () => {
+ setAuthSession([]);
+ props.onHide();
+ };
+
+ const handleShow = async () => {
+ let authlogs = [];
+
+ try {
+ setLoader(true);
+ const authResp = await fetchApi({
+ url: "xusers/authSessions",
+ params: {
+ id: props.data
+ }
+ });
+ authlogs = authResp.data.vXAuthSessions || [];
+ } catch (error) {
+ console.error(`Error occurred while fetching session logs : ${error}`);
+ }
+
+ setAuthSession(authlogs);
+ setLoader(false);
+ };
+
+ const setSessionId = () => {
+ props.onHide();
+ const currentParams = Object.fromEntries([...searchParams]);
+ if (!has(currentParams, "sessionId")) {
+ props.updateSessionId(props.data);
+ }
+ };
+
+ return (
+ <Modal show={props.show} size="lg" onHide={hideSessionModal}>
+ <Modal.Header closeButton>
+ <Modal.Title>Session Detail</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ {loader ? (
+ <ModalLoader />
+ ) : (
+ <React.Fragment>
+ {!isEmpty(authSession) && (
+ <Table bordered hover>
+ <tbody>
+ <tr>
+ <th>Login ID</th>
+ <td>
+ {authSession.map((obj) => {
+ return obj.loginId;
+ })}
+ </td>
+ </tr>
+ <tr>
+ <th>Result</th>
+ <td>
+ {authSession.map((obj) => {
+ let result = "";
+ Object.keys(AuthStatus).map((item) => {
+ if (obj.authStatus == AuthStatus[item].value) {
+ let label = AuthStatus[item].label;
+ if (AuthStatus[item].value == 1) {
+ result = label;
+ } else if (AuthStatus[item].value == 2) {
+ result = label;
+ } else {
+ result = label;
+ }
+ }
+ });
+ return result;
+ })}
+ </td>
+ </tr>
+ <tr>
+ <th>Login Type</th>
+ <td>
+ {authSession.map((obj) => {
+ let loginType = "";
+ Object.keys(AuthType).map((item) => {
+ if (obj.authType == AuthType[item].value) {
+ return (loginType = AuthType[item].label);
+ }
+ });
+ return loginType;
+ })}
+ </td>
+ </tr>
+ <tr>
+ <th>IP</th>
+ <td>
+ {authSession.map((obj) => {
+ return obj.requestIP;
+ })}
+ </td>
+ </tr>
+ <tr>
+ <th>User Agent</th>
+ <td>
+ {authSession.map((obj) => {
+ return obj.requestUserAgent;
+ })}
+ </td>
+ </tr>
+ <tr>
+ <th>Login Time</th>
+ <td>
+ {authSession.map((obj) => {
+ return currentTimeZone(obj.authTime);
+ })}
+ </td>
+ </tr>
+ </tbody>
+ </Table>
+ )}
+ </React.Fragment>
+ )}
+ <Button
+ variant="link"
+ className="link-tag"
+ size="sm"
+ onClick={setSessionId}
+ data-id="showAction"
+ data-cy="showAction"
+ >
+ Show Actions
+ </Button>
+ </Modal.Body>
+
+ <Modal.Footer>
+ <Button variant="primary" size="sm" onClick={hideSessionModal}>
+ OK
+ </Button>
+ </Modal.Footer>
+ </Modal>
+ );
+};
+export default AdminModal;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/OperationAdminModal.jsx
similarity index 93%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/OperationAdminModal.jsx
index 7fe0b65..ec0732e 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/OperationAdminModal.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Admin/OperationAdminModal.jsx
@@ -18,8 +18,8 @@
*/
import React, { useEffect, useState } from "react";
-import { ClassTypes } from "../../utils/XAEnums";
-import { Modal, Button, Table } from "react-bootstrap";
+import { ClassTypes } from "Utils/XAEnums";
+import { Modal, Button } from "react-bootstrap";
import { fetchApi } from "Utils/fetchAPI";
import SecurityZonelogs from "./AdminLogs/SecurityZonelogs";
import UserLogs from "./AdminLogs/UserLogs";
@@ -36,13 +36,13 @@
import SharedResourceLogs from "./AdminLogs/SharedResourceLogs";
import DataShareInDatasetLogs from "./AdminLogs/DataShareInDatasetLogs";
import DatasetInProjectLogs from "./AdminLogs/DatasetInProjectLogs";
-import { ModalLoader } from "../../components/CommonComponents";
+import { ModalLoader } from "Components/CommonComponents";
export const OperationAdminModal = ({ onHide, show, data = {} }) => {
const [reportdata, setReportData] = useState([]);
const [loader, setLoader] = useState(false);
- const [showview, setShowview] = useState(null);
- const { objectClassType, action, objectId, transactionId } = data;
+
+ const { objectClassType, action, transactionId } = data;
useEffect(() => {
show && rowModal();
@@ -61,7 +61,6 @@
console.error(`Error occurred while fetching Admin logs! ${error}`);
}
- setShowview(objectId);
setReportData(authlogs);
setLoader(false);
};
@@ -69,7 +68,7 @@
return (
<Modal show={show} size="lg" onHide={onHide}>
<Modal.Header closeButton>
- <Modal.Title>Operation :{action || ""}</Modal.Title>
+ <Modal.Title>Operation : {action || ""}</Modal.Title>
</Modal.Header>
<Modal.Body className="overflow-auto p-3 mb-3 mb-md-0 me-md-3">
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminModal.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminModal.jsx
deleted file mode 100644
index 449889c..0000000
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/AdminModal.jsx
+++ /dev/null
@@ -1,167 +0,0 @@
-/*
- * 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, { useEffect, useState } from "react";
-import { useSearchParams } from "react-router-dom";
-import { fetchApi } from "Utils/fetchAPI";
-import { AuthStatus, AuthType } from "../../utils/XAEnums";
-import { Modal, Table, Button } from "react-bootstrap";
-import { has } from "lodash";
-import { ModalLoader } from "../../components/CommonComponents";
-import { currentTimeZone } from "../../utils/XAUtils";
-
-export const AdminModal = (props) => {
- const [authSession, setAuthSession] = useState([]);
- const [loader, setLoader] = useState(true);
- const [searchParams] = useSearchParams();
-
- useEffect(() => {
- if (props.show) {
- handleShow();
- }
- }, [props.show]);
- const handleShow = async () => {
- let authlogs = [];
- try {
- setLoader(true);
- const authResp = await fetchApi({
- url: "xusers/authSessions",
- params: {
- id: props.data
- }
- });
- authlogs = authResp.data.vXAuthSessions;
- setAuthSession(authlogs);
- setLoader(false);
- } catch (error) {
- setLoader(false);
- console.error(`Error occurred while fetching Admin logs! ${error}`);
- }
- };
-
- const setSessionId = () => {
- props.onHide();
- const currentParams = Object.fromEntries([...searchParams]);
- if (!has(currentParams, "sessionId")) {
- props.updateSessionId(props.data);
- }
- };
-
- return (
- <Modal show={props.show} size="lg" onHide={props.onHide}>
- <Modal.Header closeButton>
- <Modal.Title>Session Detail</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- {loader ? (
- <ModalLoader />
- ) : (
- <Table bordered hover>
- <tbody>
- <tr>
- <th>Login ID</th>
- <td>
- {authSession.map((obj) => {
- return obj.loginId;
- })}
- </td>
- </tr>
- <tr>
- <th>Result</th>
- <td>
- {authSession.map((obj) => {
- var result = "";
- Object.keys(AuthStatus).map((item) => {
- if (obj.authStatus == AuthStatus[item].value) {
- let label = AuthStatus[item].label;
- if (AuthStatus[item].value == 1) {
- result = label;
- } else if (AuthStatus[item].value == 2) {
- result = label;
- } else {
- result = label;
- }
- }
- });
- return result;
- })}
- </td>
- </tr>
- <tr>
- <th>Login Type</th>
- <td>
- {authSession.map((obj) => {
- var type = "";
- Object.keys(AuthType).map((item) => {
- if (obj.authType == AuthType[item].value) {
- return (type = AuthType[item].label);
- }
- });
- return type;
- })}
- </td>
- </tr>
- <tr>
- <th>IP</th>
- <td>
- {authSession.map((obj) => {
- return obj.requestIP;
- })}
- </td>
- </tr>
- <tr>
- <th>User Agent</th>
- <td>
- {authSession.map((obj) => {
- return obj.requestUserAgent;
- })}
- </td>
- </tr>
- <tr>
- <th>Login Time</th>
- <td>
- {authSession.map((obj) => {
- return currentTimeZone(obj.authTime);
- })}
- </td>
- </tr>
- </tbody>
- </Table>
- )}
- <Button
- variant="link"
- className="link-tag"
- size="sm"
- onClick={setSessionId}
- data-id="showAction"
- data-cy="showAction"
- >
- Show Actions
- </Button>
- </Modal.Body>
-
- <Modal.Footer>
- <Button variant="primary" size="sm" onClick={props.onHide}>
- OK
- </Button>
- </Modal.Footer>
- </Modal>
- );
-};
-export default AdminModal;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/LoginSessionsLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/LoginSessions/LoginSessionsLogs.jsx
similarity index 69%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/LoginSessionsLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/LoginSessions/LoginSessionsLogs.jsx
index cb7c8f6..87df74a 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/LoginSessionsLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/LoginSessions/LoginSessionsLogs.jsx
@@ -17,18 +17,18 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
-import { useSearchParams, useNavigate } from "react-router-dom";
+import React, { useCallback, useEffect, useReducer } from "react";
+import { useSearchParams, useNavigate, useLocation } from "react-router-dom";
import { Badge, Row, Col } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
import { fetchApi } from "Utils/fetchAPI";
-import { AuthStatus, AuthType } from "../../utils/XAEnums";
-import AdminModal from "./AdminModal";
+import { AuthStatus, AuthType } from "Utils/XAEnums";
+import AdminModal from "Views/AuditEvent/Admin/AdminModal";
import dateFormat from "dateformat";
-import { AuditFilterEntries } from "Components/CommonComponents";
+import { AuditFilterEntries, Loader } from "Components/CommonComponents";
import moment from "moment-timezone";
-import { sortBy } from "lodash";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
+import { pick, sortBy } from "lodash";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import {
getTableSortBy,
getTableSortType,
@@ -36,34 +36,42 @@
parseSearchFilter,
serverError,
currentTimeZone
-} from "../../utils/XAUtils";
-import { Loader } from "../../components/CommonComponents";
+} from "Utils/XAUtils";
+import { ACTIONS } from "Views/AuditEvent/action";
+import {
+ reducer,
+ LOGIN_SESSIONS_INITIAL_STATE
+} from "Views/AuditEvent/reducer";
-function LoginSessions() {
- const [loginSessionListingData, setLoginSessionLogs] = useState([]);
- const [loader, setLoader] = useState(true);
- const [sessionId, setSessionId] = useState([]);
- const [showmodal, setShowModal] = useState(false);
- const [pageCount, setPageCount] = React.useState(0);
- const [entries, setEntries] = useState([]);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const fetchIdRef = useRef(0);
- const [contentLoader, setContentLoader] = useState(true);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [resetPage, setResetpage] = useState({ page: null });
- const handleClose = () => setShowModal(false);
+function LoginSessionsLogs() {
+ const [state, dispatch] = useReducer(reducer, LOGIN_SESSIONS_INITIAL_STATE);
+
+ const location = useLocation();
const navigate = useNavigate();
+ const [searchParams, setSearchParams] = useSearchParams();
+
+ const hideSessionModal = () =>
+ dispatch({
+ type: ACTIONS.SHOW_SESSION_MODAL,
+ showSessionModal: false,
+ sessionId: undefined
+ });
+
+ const openSessionModal = (id) => {
+ dispatch({
+ type: ACTIONS.SHOW_SESSION_MODAL,
+ showSessionModal: true,
+ sessionId: id
+ });
+ };
+
const updateSessionId = (id) => {
navigate(`/reports/audit/admin?sessionId=${id}`);
};
useEffect(() => {
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams(
"loginSession",
searchParams,
@@ -73,52 +81,70 @@
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("loginSession", JSON.stringify(searchParam));
- setContentLoader(false);
- }, [searchParams]);
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ }, [location.search]);
const fetchLoginSessionLogsInfo = useCallback(
async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
- setLoader(true);
- let logsResp = [];
- let logs = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- if (sortBy.length > 0) {
- params["sortBy"] = getTableSortBy(sortBy);
- params["sortType"] = getTableSortType(sortBy);
- }
- try {
- logsResp = await fetchApi({
- url: "xusers/authSessions",
- params: params,
- skipNavigate: true
- });
- logs = logsResp.data.vXAuthSessions;
- totalCount = logsResp.data.totalCount;
- } catch (error) {
- serverError(error);
- console.error(
- `Error occurred while fetching Login Session logs! ${error}`
- );
- }
- setLoginSessionLogs(logs);
- setEntries(logsResp.data);
- setPageCount(Math.ceil(totalCount / pageSize));
- setResetpage({ page: gotoPage });
- setLoader(false);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize,
+ ...(sortBy.length > 0 && {
+ sortBy: getTableSortBy(sortBy),
+ sortType: getTableSortType(sortBy)
+ })
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "xusers/authSessions",
+ params: params,
+ skipNavigate: true
+ });
+
+ const logsEntries = pick(response.data, [
+ "startIndex",
+ "pageSize",
+ "totalCount",
+ "resultSize"
+ ]);
+ const logsResp = response.data?.vXAuthSessions || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: logsResp,
+ entries: logsEntries,
+ pageCount: Math.ceil(totalCount / pageSize),
+ resetPage: { page: gotoPage }
+ });
+ } catch (error) {
+ serverError(error);
+ console.error(
+ `Error occurred while fetching Login Session logs! ${error}`
+ );
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
const getDefaultSort = React.useMemo(
@@ -132,14 +158,11 @@
);
const refreshTable = () => {
- setLoginSessionLogs([]);
- setLoader(true);
- setUpdateTable(moment.now());
- };
-
- const openModal = (id) => {
- setShowModal(true);
- setSessionId(id);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
};
const columns = React.useMemo(
@@ -156,7 +179,7 @@
role="button"
className="text-primary"
onClick={() => {
- openModal(id);
+ openSessionModal(id);
}}
data-id={id}
data-cy={id}
@@ -291,17 +314,22 @@
);
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
localStorage.setItem("loginSession", JSON.stringify(searchParam));
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
@@ -374,7 +402,7 @@
}
];
- return contentLoader ? (
+ return state.contentLoader ? (
<Loader />
) : (
<div className="wrap">
@@ -387,26 +415,32 @@
placeholder="Search for your login sessions..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</div>
</Col>
</Row>
- <AuditFilterEntries entries={entries} refreshTable={refreshTable} />
+
+ <AuditFilterEntries
+ entries={state.entries}
+ refreshTable={refreshTable}
+ />
+
<XATableLayout
- data={loginSessionListingData}
+ data={state.tableListingData}
columns={columns}
fetchData={fetchLoginSessionLogsInfo}
- totalCount={entries && entries.totalCount}
- loading={loader}
- pageCount={pageCount}
+ totalCount={state.entries && state.entries.totalCount}
+ loading={state.loader}
+ pageCount={state.pageCount}
columnSort={true}
defaultSort={getDefaultSort}
/>
+
<AdminModal
- show={showmodal}
- data={sessionId}
- onHide={handleClose}
+ show={state.showSessionModal}
+ data={state.sessionId}
+ onHide={hideSessionModal}
updateSessionId={updateSessionId}
></AdminModal>
</React.Fragment>
@@ -414,4 +448,4 @@
);
}
-export default LoginSessions;
+export default LoginSessionsLogs;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginStatusLogs.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginStatus/PluginStatusLogs.jsx
similarity index 84%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginStatusLogs.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginStatus/PluginStatusLogs.jsx
index 63524cd..8be66a7 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginStatusLogs.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginStatus/PluginStatusLogs.jsx
@@ -17,11 +17,14 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
-import { useSearchParams, useOutletContext } from "react-router-dom";
+import React, { useCallback, useEffect, useReducer } from "react";
+import {
+ useSearchParams,
+ useOutletContext,
+ useLocation
+} from "react-router-dom";
import { Row, Col } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
-import { AuditFilterEntries } from "Components/CommonComponents";
import moment from "moment-timezone";
import {
setTimeStamp,
@@ -32,11 +35,12 @@
isKMSAuditor
} from "Utils/XAUtils";
import {
+ AuditFilterEntries,
CustomPopover,
CustomTooltip,
Loader
-} from "../../components/CommonComponents";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
+} from "Components/CommonComponents";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import { fetchApi } from "Utils/fetchAPI";
import {
isUndefined,
@@ -47,35 +51,30 @@
isNull,
isEmpty,
cloneDeep,
- get
+ get,
+ pick
} from "lodash";
-import { getServiceDef } from "../../utils/appState";
-import { pluginStatusColumnInfo } from "../../utils/XAMessages";
-import { pluginStatusColumnInfoMsg } from "../../utils/XAEnums";
+import { getServiceDef } from "Utils/appState";
+import { pluginStatusColumnInfo } from "Utils/XAMessages";
+import { pluginStatusColumnInfoMsg } from "Utils/XAEnums";
+import { ACTIONS } from "Views/AuditEvent/action";
+import { reducer, PLUGIN_STATUS_INITIAL_STATE } from "Views/AuditEvent/reducer";
-function Plugin_Status() {
- const context = useOutletContext();
- const services = context.services;
- const servicesAvailable = context.servicesAvailable;
- const [pluginStatusListingData, setPluginStatusLogs] = useState([]);
- const [loader, setLoader] = useState(true);
- const [entries, setEntries] = useState([]);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const fetchIdRef = useRef(0);
- const [contentLoader, setContentLoader] = useState(true);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [resetPage, setResetpage] = useState({ page: null });
- const isKMSRole = isKeyAdmin() || isKMSAuditor();
+function PluginStatusLogs() {
+ const [state, dispatch] = useReducer(reducer, PLUGIN_STATUS_INITIAL_STATE);
+
+ const location = useLocation();
+
+ const { services, servicesAvailable } = useOutletContext();
+
const { allServiceDefs } = cloneDeep(getServiceDef());
- const [pageCount, setPageCount] = React.useState(0);
+ const isKMSRole = isKeyAdmin() || isKMSAuditor();
+
+ const [searchParams, setSearchParams] = useSearchParams();
useEffect(() => {
if (servicesAvailable !== null) {
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams(
"pluginStatus",
searchParams,
@@ -85,50 +84,67 @@
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("pluginStatus", JSON.stringify(searchParam));
- setContentLoader(false);
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
}
- }, [searchParams, servicesAvailable]);
+ }, [location.search, servicesAvailable]);
const fetchPluginStatusInfo = useCallback(
async ({ pageSize, pageIndex, gotoPage }) => {
- setLoader(true);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
if (servicesAvailable !== null) {
- let logsResp = [];
- let logs = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- try {
- logsResp = await fetchApi({
- url: "plugins/plugins/info",
- params: params
- });
- logs = logsResp.data.pluginInfoList;
- totalCount = logsResp.data.totalCount;
- } catch (error) {
- serverError(error);
- console.error(
- `Error occurred while fetching Plugin Status logs! ${error}`
- );
- }
- setPluginStatusLogs(logs);
- setEntries(logsResp.data);
- setPageCount(Math.ceil(totalCount / pageSize));
- setResetpage({ page: gotoPage });
- setLoader(false);
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "plugins/plugins/info",
+ params: params
+ });
+
+ const logsEntries = pick(response.data, [
+ "startIndex",
+ "pageSize",
+ "totalCount",
+ "resultSize"
+ ]);
+ const logsResp = response.data?.pluginInfoList || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: logsResp,
+ entries: logsEntries,
+ pageCount: Math.ceil(totalCount / pageSize),
+ resetPage: { page: gotoPage }
+ });
+ } catch (error) {
+ serverError(error);
+ console.error(
+ `Error occurred while fetching Plugin Status logs! ${error}`
+ );
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
}
},
- [updateTable, searchFilterParams, servicesAvailable]
+ [state.refreshTableData, servicesAvailable]
);
const isDateDifferenceMoreThanHr = (date1, date2) => {
@@ -227,9 +243,11 @@
};
const refreshTable = () => {
- setPluginStatusLogs([]);
- setLoader(true);
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
};
const infoIcon = (columnsName) => {
@@ -589,17 +607,22 @@
);
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
localStorage.setItem("pluginStatus", JSON.stringify(searchParam));
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
@@ -671,7 +694,7 @@
}
];
- return contentLoader ? (
+ return state.contentLoader ? (
<Loader />
) : (
<div className="wrap">
@@ -684,29 +707,31 @@
placeholder="Search for your plugin status..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</div>
</Col>
</Row>
+
<div className="position-relative">
<Row>
<Col sm={11}>
<AuditFilterEntries
- entries={entries}
+ entries={state.entries}
refreshTable={refreshTable}
/>
</Col>
</Row>
+
<XATableLayout
- data={pluginStatusListingData}
+ data={state.tableListingData}
columns={columns}
- loading={loader}
- totalCount={entries && entries.totalCount}
+ loading={state.loader}
+ totalCount={state.entries && state.entries.totalCount}
fetchData={fetchPluginStatusInfo}
+ pageCount={state.pageCount}
columnSort={true}
clientSideSorting={true}
- pageCount={pageCount}
columnHide={{ tableName: "pluginStatus", isVisible: true }}
/>
</div>
@@ -715,4 +740,4 @@
);
}
-export default Plugin_Status;
+export default PluginStatusLogs;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginsLog.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Plugins/PluginsLogs.jsx
similarity index 65%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginsLog.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Plugins/PluginsLogs.jsx
index c1ad383..80b34f9 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/PluginsLog.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/Plugins/PluginsLogs.jsx
@@ -17,15 +17,19 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
-import { useSearchParams, useOutletContext } from "react-router-dom";
+import React, { useCallback, useEffect, useReducer } from "react";
+import {
+ useSearchParams,
+ useOutletContext,
+ useLocation
+} from "react-router-dom";
import { Badge, Row, Col } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
-import { AuditFilterEntries } from "Components/CommonComponents";
+import { AuditFilterEntries, Loader } from "Components/CommonComponents";
import moment from "moment-timezone";
import dateFormat from "dateformat";
-import { sortBy, filter, isEmpty } from "lodash";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
+import { sortBy, filter, isEmpty, pick } from "lodash";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import { fetchApi } from "Utils/fetchAPI";
import {
getTableSortBy,
@@ -36,101 +40,98 @@
isKeyAdmin,
isKMSAuditor,
currentTimeZone
-} from "../../utils/XAUtils";
-import { Loader } from "../../components/CommonComponents";
+} from "Utils/XAUtils";
+import { ACTIONS } from "Views/AuditEvent/action";
+import { reducer, PLUGINS_INITIAL_STATE } from "Views/AuditEvent/reducer";
-function Plugins() {
- const context = useOutletContext();
- const services = context.services;
- const [pluginsListingData, setPluginsLogs] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageCount, setPageCount] = React.useState(0);
- const [entries, setEntries] = useState([]);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const fetchIdRef = useRef(0);
- //const [services, setServices] = useState([]);
- const [contentLoader, setContentLoader] = useState(true);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [resetPage, setResetpage] = useState({ page: null });
+function PluginsLogs() {
+ const [state, dispatch] = useReducer(reducer, PLUGINS_INITIAL_STATE);
+
+ const location = useLocation();
+
+ const { services } = useOutletContext();
+
const isKMSRole = isKeyAdmin() || isKMSAuditor();
+ const [searchParams, setSearchParams] = useSearchParams();
+
useEffect(() => {
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams("agent", searchParams, searchFilterOptions);
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
- }
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- localStorage.setItem("agent", JSON.stringify(searchParam));
- setContentLoader(false);
- }, [searchParams]);
-
- /* const fetchServices = async () => {
- let servicesResp = [];
- try {
- servicesResp = await fetchApi({
- url: "plugins/services"
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
});
- } catch (error) {
- console.error(
- `Error occurred while fetching Services or CSRF headers! ${error}`
- );
}
-
- setServices(servicesResp.data.services);
- setLoader(false);
- }; */
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ localStorage.setItem("agent", JSON.stringify(searchParam));
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ }, [location.search]);
const fetchPluginsInfo = useCallback(
async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
- setLoader(true);
- let logsResp = [];
- let logs = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- if (sortBy.length > 0) {
- params["sortBy"] = getTableSortBy(sortBy);
- params["sortType"] = getTableSortType(sortBy);
- }
- try {
- logsResp = await fetchApi({
- url: "assets/exportAudit",
- params: params,
- skipNavigate: true
- });
- logs = logsResp.data.vXPolicyExportAudits;
- totalCount = logsResp.data.totalCount;
- } catch (error) {
- serverError(error);
- console.error(`Error occurred while fetching Plugins logs! ${error}`);
- }
- setPluginsLogs(logs);
- setEntries(logsResp.data);
- setPageCount(Math.ceil(totalCount / pageSize));
- setResetpage({ page: gotoPage });
- setLoader(false);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize,
+ ...(sortBy.length > 0 && {
+ sortBy: getTableSortBy(sortBy),
+ sortType: getTableSortType(sortBy)
+ })
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "assets/exportAudit",
+ params: params,
+ skipNavigate: true
+ });
+
+ const logsEntries = pick(response.data, [
+ "startIndex",
+ "pageSize",
+ "totalCount",
+ "resultSize"
+ ]);
+ const logsResp = response.data?.vXPolicyExportAudits || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: logsResp,
+ entries: logsEntries,
+ pageCount: Math.ceil(totalCount / pageSize),
+ resetPage: { page: gotoPage }
+ });
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching Plugins logs! ${error}`);
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
const refreshTable = () => {
- setPluginsLogs([]);
- setLoader(true);
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
};
const columns = React.useMemo(
@@ -248,17 +249,22 @@
);
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
localStorage.setItem("agent", JSON.stringify(searchParam));
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
@@ -322,7 +328,7 @@
}
];
- return contentLoader ? (
+ return state.contentLoader ? (
<Loader />
) : (
<div className="wrap">
@@ -335,19 +341,24 @@
placeholder="Search for your plugins..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</div>
</Col>
</Row>
- <AuditFilterEntries entries={entries} refreshTable={refreshTable} />
+
+ <AuditFilterEntries
+ entries={state.entries}
+ refreshTable={refreshTable}
+ />
+
<XATableLayout
- data={pluginsListingData}
+ data={state.tableListingData}
columns={columns}
- loading={loader}
- totalCount={entries && entries.totalCount}
+ loading={state.loader}
+ totalCount={state.entries && state.entries.totalCount}
fetchData={fetchPluginsInfo}
- pageCount={pageCount}
+ pageCount={state.pageCount}
columnSort={true}
defaultSort={getDefaultSort}
/>
@@ -356,4 +367,4 @@
);
}
-export default Plugins;
+export default PluginsLogs;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/UserSync.jsx b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/UserSync/UserSyncLogs.jsx
similarity index 63%
rename from security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/UserSync.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/UserSync/UserSyncLogs.jsx
index 0dcf658..181e6d0 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/UserSync.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/UserSync/UserSyncLogs.jsx
@@ -17,54 +17,61 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
-import { useSearchParams } from "react-router-dom";
+import React, { useCallback, useEffect, useReducer } from "react";
+import { useSearchParams, useLocation } from "react-router-dom";
import { Badge, Modal, Button, Row, Col } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
import { AuditFilterEntries, Loader } from "Components/CommonComponents";
-import { SyncSourceDetails } from "../UserGroupRoleListing/SyncSourceDetails";
+import { SyncSourceDetails } from "Views/UserGroupRoleListing/SyncSourceDetails";
import dateFormat from "dateformat";
import moment from "moment-timezone";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
-import { sortBy, has } from "lodash";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
+import { fetchApi } from "Utils/fetchAPI";
+import { sortBy, has, pick } from "lodash";
import {
getTableSortBy,
getTableSortType,
fetchSearchFilterParams,
parseSearchFilter,
serverError
-} from "../../utils/XAUtils";
+} from "Utils/XAUtils";
+import { ACTIONS } from "Views/AuditEvent/action";
+import { reducer, USERSYNC_INITIAL_STATE } from "Views/AuditEvent/reducer";
-function User_Sync() {
- const [userSyncListingData, setUserSyncLogs] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageCount, setPageCount] = React.useState(0);
- const fetchIdRef = useRef(0);
- const [entries, setEntries] = useState([]);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [showTableSyncDetails, setTableSyncdetails] = useState({
- syncDteails: {},
- showSyncDetails: false
- });
- const [contentLoader, setContentLoader] = useState(true);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
+function UserSync() {
+ const [state, dispatch] = useReducer(reducer, USERSYNC_INITIAL_STATE);
+
+ const location = useLocation();
+
const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [resetPage, setResetpage] = useState({ page: null });
+
+ const openSyncTableModal = (data) => {
+ dispatch({
+ type: ACTIONS.SHOW_SYNC_TABLE_MODAL,
+ showSyncTableModal: true,
+ syncTableData: data
+ });
+ };
+
+ const closeSyncTableModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_SYNC_TABLE_MODAL,
+ showSyncTableModal: false,
+ syncTableData: {}
+ });
+ };
useEffect(() => {
- let currentDate = moment(moment()).format("MM/DD/YYYY");
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const currentDate = moment(moment()).format("MM/DD/YYYY");
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams("userSync", searchParams, searchFilterOptions);
if (
!has(searchFilterParam, "startDate") &&
!has(searchFilterParam, "endDate")
) {
- searchParam["startDate"] = currentDate;
- searchFilterParam["startDate"] = currentDate;
+ searchParam.startDate = currentDate;
+ searchFilterParam.startDate = currentDate;
defaultSearchFilterParam.push({
category: "startDate",
value: currentDate
@@ -73,84 +80,93 @@
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
- setSearchFilterParams(searchFilterParam);
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("userSync", JSON.stringify(searchParam));
- setContentLoader(false);
}, []);
useEffect(() => {
- let { searchFilterParam, defaultSearchFilterParam, searchParam } =
+ const { searchFilterParam, defaultSearchFilterParam, searchParam } =
fetchSearchFilterParams("userSync", searchParams, searchFilterOptions);
// Updating the states for search params, search filter, default search filter and localStorage
setSearchParams(searchParam, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
localStorage.setItem("userSync", JSON.stringify(searchParam));
- setContentLoader(false);
- }, [searchParams]);
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ }, [location.search]);
const fetchUserSyncInfo = useCallback(
async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
- setLoader(true);
- let logsResp = [];
- let logs = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- if (sortBy.length > 0) {
- params["sortBy"] = getTableSortBy(sortBy);
- params["sortType"] = getTableSortType(sortBy);
- }
- try {
- const { fetchApi } = await import("Utils/fetchAPI");
- logsResp = await fetchApi({
- url: "assets/ugsyncAudits",
- params: params
- });
- logs = logsResp.data.vxUgsyncAuditInfoList;
- totalCount = logsResp.data.totalCount;
- } catch (error) {
- serverError(error);
- console.error(
- `Error occurred while fetching User Sync logs! ${error}`
- );
- }
- setUserSyncLogs(logs);
- setEntries(logsResp.data);
- setPageCount(Math.ceil(totalCount / pageSize));
- setResetpage({ page: gotoPage });
- setLoader(false);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize,
+ ...(sortBy.length > 0 && {
+ sortBy: getTableSortBy(sortBy),
+ sortType: getTableSortType(sortBy)
+ })
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "assets/ugsyncAudits",
+ params: params
+ });
+
+ const logsEntries = pick(response.data, [
+ "startIndex",
+ "pageSize",
+ "totalCount",
+ "resultSize"
+ ]);
+ const logsResp = response.data?.vxUgsyncAuditInfoList || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: logsResp,
+ entries: logsEntries,
+ pageCount: Math.ceil(totalCount / pageSize),
+ resetPage: { page: gotoPage }
+ });
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching User Sync logs! ${error}`);
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
const refreshTable = () => {
- setUserSyncLogs([]);
- setLoader(true);
- setUpdateTable(moment.now());
- };
-
- const toggleTableSyncModal = (raw) => {
- setTableSyncdetails({
- syncDteails: raw,
- showSyncDetails: true
- });
- };
-
- const toggleTableSyncModalClose = () => {
- setTableSyncdetails({
- syncDteails: {},
- showSyncDetails: false
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
});
};
@@ -270,7 +286,7 @@
{
Header: "Sync Details",
accessor: "syncSourceInfo",
- Cell: (rawValue, model) => {
+ Cell: (rawValue) => {
if (rawValue.value) {
return (
<div className="text-center">
@@ -279,9 +295,8 @@
data-id="syncDetailes"
data-cy="syncDetailes"
title="Sync Details"
- id={model.id}
onClick={() => {
- toggleTableSyncModal(rawValue.value);
+ openSyncTableModal(rawValue.value);
}}
>
<i className="fa-fw fa fa-eye"> </i>
@@ -299,17 +314,22 @@
);
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
localStorage.setItem("userSync", JSON.stringify(searchParam));
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
@@ -347,7 +367,7 @@
}
];
- return contentLoader ? (
+ return state.contentLoader ? (
<Loader />
) : (
<div className="wrap">
@@ -360,41 +380,43 @@
placeholder="Search for your user sync audits..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</div>
</Col>
</Row>
- <AuditFilterEntries entries={entries} refreshTable={refreshTable} />
+
+ <AuditFilterEntries
+ entries={state.entries}
+ refreshTable={refreshTable}
+ />
+
<XATableLayout
- data={userSyncListingData}
+ data={state.tableListingData}
columns={columns}
- loading={loader}
- totalCount={entries && entries.totalCount}
+ loading={state.loader}
+ totalCount={state.entries && state.entries.totalCount}
fetchData={fetchUserSyncInfo}
- pageCount={pageCount}
+ pageCount={state.pageCount}
columnSort={true}
defaultSort={getDefaultSort}
/>
+
<Modal
- show={showTableSyncDetails && showTableSyncDetails.showSyncDetails}
- onHide={toggleTableSyncModalClose}
+ show={state.showSyncTableModal}
+ onHide={closeSyncTableModal}
size="xl"
>
- <Modal.Header>
+ <Modal.Header closeButton>
<Modal.Title>Sync Source Details</Modal.Title>
</Modal.Header>
<Modal.Body>
<SyncSourceDetails
- syncDetails={showTableSyncDetails.syncDteails}
+ syncDetails={state.syncTableData}
></SyncSourceDetails>
</Modal.Body>
<Modal.Footer>
- <Button
- variant="primary"
- size="sm"
- onClick={toggleTableSyncModalClose}
- >
+ <Button variant="primary" size="sm" onClick={closeSyncTableModal}>
OK
</Button>
</Modal.Footer>
@@ -404,4 +426,4 @@
);
}
-export default User_Sync;
+export default UserSync;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/action.js b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/action.js
new file mode 100644
index 0000000..9379f10
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/action.js
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+export const ACTIONS = {
+ SET_TABLE_LOADER: "set-table-loader",
+ SET_CONTENT_LOADER: "set-content-loader",
+ SET_SEARCH_FILTER_PARAMS: "set-search-filter-params",
+ SET_DEFAULT_SEARCH_FILTER_PARAMS: "set-default-search-filter-params",
+ SET_TABLE_DATA: "set-table-data",
+ SHOW_POLICY_MODAL: "show-policy-modal",
+ SHOW_ROW_MODAL: "show-row-modal",
+ SHOW_SESSION_MODAL: "show-session-modal",
+ SHOW_SYNC_TABLE_MODAL: "show-sync-table-modal",
+ SET_SECURITY_ZONES: "set-security-zones"
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/reducer.js b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/reducer.js
new file mode 100644
index 0000000..b1223d4
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/AuditEvent/reducer.js
@@ -0,0 +1,138 @@
+/*
+ * 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 moment from "moment-timezone";
+import { ACTIONS } from "./action";
+
+// Shared initial state
+export const INITIAL_STATE = {
+ loader: true,
+ contentLoader: true,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ tableListingData: [],
+ pageCount: 0,
+ entries: {},
+ resetPage: { page: 0 },
+ refreshTableData: moment.now()
+};
+
+// Specific initial states
+export const ACCESS_INITIAL_STATE = {
+ ...INITIAL_STATE,
+ securityZones: [],
+ showRowModal: false,
+ rowData: {},
+ showPolicyModal: false,
+ policyData: null
+};
+
+export const ADMIN_INITIAL_STATE = {
+ ...INITIAL_STATE,
+ showRowModal: false,
+ rowData: {},
+ showSessionModal: false,
+ sessionId: undefined
+};
+
+export const LOGIN_SESSIONS_INITIAL_STATE = {
+ ...INITIAL_STATE,
+ showSessionModal: false,
+ sessionId: undefined
+};
+
+export const PLUGINS_INITIAL_STATE = {
+ ...INITIAL_STATE
+};
+
+export const PLUGIN_STATUS_INITIAL_STATE = {
+ ...INITIAL_STATE
+};
+
+export const USERSYNC_INITIAL_STATE = {
+ ...INITIAL_STATE,
+ showSyncTableModal: false,
+ syncTableData: {}
+};
+
+// Shared reducer function
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.SET_TABLE_LOADER:
+ return {
+ ...state,
+ loader: action.loader
+ };
+ case ACTIONS.SET_CONTENT_LOADER:
+ return {
+ ...state,
+ contentLoader: action.contentLoader
+ };
+ case ACTIONS.SET_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case ACTIONS.SET_TABLE_DATA:
+ return {
+ ...state,
+ tableListingData: action.tableListingData,
+ entries: action.entries,
+ pageCount: action.pageCount,
+ resetPage: action.resetPage
+ };
+ case ACTIONS.SHOW_POLICY_MODAL:
+ return {
+ ...state,
+ showPolicyModal: action.showPolicyModal,
+ policyData: action.policyData
+ };
+ case ACTIONS.SHOW_ROW_MODAL:
+ return {
+ ...state,
+ showRowModal: action.showRowModal,
+ rowData: action.rowData
+ };
+ case ACTIONS.SHOW_SESSION_MODAL:
+ return {
+ ...state,
+ showSessionModal: action.showSessionModal,
+ sessionId: action.sessionId
+ };
+ case ACTIONS.SHOW_SYNC_TABLE_MODAL:
+ return {
+ ...state,
+ showSyncTableModal: action.showSyncTableModal,
+ syncTableData: action.syncTableData
+ };
+ case ACTIONS.SET_SECURITY_ZONES:
+ return {
+ ...state,
+ securityZones: action.securityZones
+ };
+ default:
+ return state;
+ }
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyCreate.jsx b/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyCreate.jsx
index 5a9fe06..fcb8a95 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyCreate.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyCreate.jsx
@@ -17,32 +17,30 @@
* under the License.
*/
-import React, { useReducer, useEffect, useState, useRef } from "react";
+import React, { useReducer, useEffect, useRef } from "react";
import { Button, Table, Row, Col } from "react-bootstrap";
import { Form, Field } from "react-final-form";
import { toast } from "react-toastify";
import { FieldArray } from "react-final-form-arrays";
import arrayMutators from "final-form-arrays";
import { fetchApi } from "Utils/fetchAPI";
-import {
- BlockUi,
- Loader,
- scrollToError
-} from "../../components/CommonComponents";
-import { commonBreadcrumb, serverError } from "../../utils/XAUtils";
+import { BlockUi, Loader, scrollToError } from "Components/CommonComponents";
+import { commonBreadcrumb, serverError } from "Utils/XAUtils";
import { cloneDeep, find, isEmpty, values } from "lodash";
import withRouter from "Hooks/withRouter";
import { useLocation, useNavigate } from "react-router-dom";
import usePrompt from "Hooks/usePrompt";
-import { getServiceDef } from "../../utils/appState";
+import { getServiceDef } from "Utils/appState";
-const initialState = {
+const INITIAL_STATE = {
service: {},
definition: {},
- loader: true
+ loader: true,
+ preventUnBlock: false,
+ blockUI: false
};
-const keyCreateReducer = (state, action) => {
+const reducer = (state, action) => {
switch (action.type) {
case "SET_LOADER":
return {
@@ -56,6 +54,16 @@
definition: action.definition,
loader: action.loader
};
+ case "SET_PREVENT_ALERT":
+ return {
+ ...state,
+ preventUnBlock: action.preventUnBlock
+ };
+ case "SET_BLOCK_UI":
+ return {
+ ...state,
+ blockUI: action.blockUI
+ };
default:
throw new Error();
}
@@ -68,15 +76,15 @@
};
function KeyCreate(props) {
- const [keyDetails, dispatch] = useReducer(keyCreateReducer, initialState);
- const { loader, service, definition } = keyDetails;
- const { state } = useLocation();
const navigate = useNavigate();
- const [preventUnBlock, setPreventUnblock] = useState(false);
- const [blockUI, setBlockUI] = useState(false);
+ const { state: navigateState } = useLocation();
+
const toastId = useRef(null);
const { allServiceDefs } = cloneDeep(getServiceDef());
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
+ const { loader, service, definition, preventUnBlock, blockUI } = state;
+
useEffect(() => {
fetchInitialData();
}, []);
@@ -124,9 +132,17 @@
values.attributes[key].value;
}
}
- setPreventUnblock(true);
+
+ dispatch({
+ type: "SET_PREVENT_ALERT",
+ preventUnBlock: true
+ });
+
try {
- setBlockUI(true);
+ dispatch({
+ type: "SET_BLOCK_UI",
+ blockUI: true
+ });
await fetchApi({
url: "keys/key",
method: "post",
@@ -135,19 +151,26 @@
},
data: serviceJson
});
- setBlockUI(false);
- toast.success(`Success! Key created successfully`);
- navigate(`/kms/keys/edit/manage/${state.detail}`, {
+ dispatch({
+ type: "SET_BLOCK_UI",
+ blockUI: false
+ });
+ toast.success(`Key created successfully`);
+ navigate(`/kms/keys/edit/manage/${navigateState.detail}`, {
state: {
- detail: state.detail
+ detail: navigateState.detail
}
});
} catch (error) {
- setBlockUI(false);
+ dispatch({
+ type: "SET_BLOCK_UI",
+ blockUI: false
+ });
serverError(error);
- console.error(`Error occurred while creating key! ${error}`);
+ console.error(`Error occurred while creating key : ${error}`);
}
};
+
const fetchKmsServices = async () => {
let serviceResp;
dispatch({
@@ -159,7 +182,7 @@
url: `plugins/services/name/${props.params.serviceName}`
});
} catch (error) {
- console.error(`Error occurred while fetching Services! ${error}`);
+ console.error(`Error occurred while fetching services : ${error}`);
}
dispatch({
@@ -173,6 +196,7 @@
const closeForm = () => {
navigate(`/kms/keys/edit/manage/${props.params.serviceName}`);
};
+
const validate = (values) => {
const errors = {};
if (!values.name) {
@@ -183,6 +207,7 @@
}
return errors;
};
+
const keyCreateBreadcrumb = () => {
let serviceDetails = {};
serviceDetails["serviceDefId"] = definition && definition?.id;
@@ -193,6 +218,7 @@
serviceDetails
);
};
+
return loader ? (
<Loader />
) : (
@@ -295,6 +321,7 @@
</Row>
)}
</Field>
+
<Field name="description">
{({ input }) => (
<Row className="form-group">
@@ -313,6 +340,7 @@
</Row>
)}
</Field>
+
<Row className="form-group">
<Col xs={3}>
<label className="form-label float-end">Attributes</label>
@@ -410,7 +438,10 @@
size="sm"
onClick={() => {
form.reset;
- setPreventUnblock(true);
+ dispatch({
+ type: "SET_PREVENT_ALERT",
+ preventUnBlock: true
+ });
closeForm();
}}
disabled={submitting}
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyManager.jsx b/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyManager.jsx
index 94b0e0d..75dc4a8 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyManager.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/Encryption/KeyManager.jsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useReducer, useCallback, useEffect, useState } from "react";
+import React, { useReducer, useCallback, useEffect } from "react";
import {
useNavigate,
useParams,
@@ -37,27 +37,31 @@
import { BlockUi } from "Components/CommonComponents";
import CustomBreadcrumb from "Views/CustomBreadcrumb";
-function init(props) {
+function INITIAL_STATE(initialArg) {
return {
loader: true,
- selcServicesData: [],
- keydata: [],
- onchangeval:
- props.params.kmsManagePage == "new"
+ keyData: [],
+ onChangeValue:
+ initialArg.params.kmsManagePage == "new"
? null
: {
- value: props.params.kmsServiceName,
- label: props.params.kmsServiceName
+ value: initialArg.params.kmsServiceName,
+ label: initialArg.params.kmsServiceName
},
- deleteshowmodal: false,
- editshowmodal: false,
- filterdata: null,
- pagecount: 0,
+ deleteShowModal: false,
+ editShowModal: false,
+ filterData: null,
+ pageCount: 0,
kmsservice: {},
- updatetable: moment.now(),
+ updateTable: moment.now(),
currentPageIndex: 0,
currentPageSize: 25,
- resetPage: { page: 0 }
+ resetPage: { page: 0 },
+ totalCount: 0,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ refreshTableData: moment.now(),
+ blockUi: false
};
}
@@ -71,42 +75,42 @@
case "SET_SEL_SERVICE":
return {
...state,
- selcServicesData: action.selcservicesData,
- keydata: action.keydatalist,
- pagecount: action.pagecount
+ keyData: action.keyDataList,
+ pageCount: action.pageCount,
+ totalCount: action.totalCount
};
case "SET_ONCHANGE_SERVICE":
return {
...state,
loader: action.loader,
- onchangeval: action.onchangeval
+ onChangeValue: action.onChangeValue
};
case "SET_DELETE_MODAL":
return {
...state,
- deleteshowmodal: action.deleteshowmodal,
- filterdata: action.filterdata
+ deleteShowModal: action.deleteShowModal,
+ filterData: action.filterData
};
case "SET_DELETE_MODAL_CLOSE":
return {
...state,
- deleteshowmodal: action.deleteshowmodal
+ deleteShowModal: action.deleteShowModal
};
case "SET_EDIT_MODAL":
return {
...state,
- editshowmodal: action.editshowmodal,
- filterdata: action.filterdata
+ editShowModal: action.editShowModal,
+ filterData: action.filterData
};
case "SET_EDIT_MODAL_CLOSE":
return {
...state,
- editshowmodal: action.editshowmodal
+ editShowModal: action.editShowModal
};
case "SET_UPDATE_TABLE":
return {
...state,
- updatetable: action.updatetable
+ updateTable: action.updateTable
};
case "SET_CURRENT_PAGE_INDEX":
return {
@@ -123,39 +127,55 @@
...state,
resetPage: action.resetPage
};
+ case "SET_SEARCH_FILTER_PARAMS":
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case "SET_DEFAULT_SEARCH_FILTER_PARAMS":
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case "SET_BLOCK_UI":
+ return {
+ ...state,
+ blockUi: action.blockUi
+ };
default:
throw new Error();
}
}
const KeyManager = () => {
- const navigate = useNavigate();
- const { state } = useLocation();
const params = useParams();
- let stateAndParams = { params: params, state: state };
- const [keyState, dispatch] = useReducer(reducer, stateAndParams, init);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
+ const navigate = useNavigate();
+ const { state: navigateState, search } = useLocation();
- const [totalCount, setTotalCount] = useState(0);
- const [blockUI, setBlockUI] = useState(false);
+ let initialArg = { params: params, navigateState: navigateState };
+ const [state, dispatch] = useReducer(reducer, initialArg, INITIAL_STATE);
+
+ const [searchParams, setSearchParams] = useSearchParams();
const {
loader,
- keydata,
- filterdata,
- onchangeval,
- deleteshowmodal,
- editshowmodal,
+ keyData,
+ filterData,
+ onChangeValue,
+ deleteShowModal,
+ editShowModal,
currentPageIndex,
currentPageSize,
- pagecount,
- updatetable,
- resetPage
- } = keyState;
+ pageCount,
+ updateTable,
+ resetPage,
+ totalCount,
+ searchFilterParams,
+ defaultSearchFilterParams,
+ refreshTableData,
+ blockUi
+ } = state;
useEffect(() => {
let searchFilterParam = {};
@@ -194,10 +214,17 @@
(!isEmpty(searchFilterParams) || !isEmpty(searchFilterParam)) &&
JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: "SET_SEARCH_FILTER_PARAMS",
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- }, [searchParams]);
+ dispatch({
+ type: "SET_DEFAULT_SEARCH_FILTER_PARAMS",
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ }, [search]);
const fetchServices = async (inputValue) => {
const allParams = {
@@ -219,7 +246,7 @@
errorMsg = `Error! ${error.response.data.msgDesc}`;
}
toast.error(errorMsg);
- console.error(`Error occurred while fetching Services! ${error}`);
+ console.error(`Error occurred while fetching services : ${error}`);
}
serviceOptions = servicesData.map((obj) => ({
@@ -230,117 +257,117 @@
return serviceOptions;
};
- const selconChange = (e) => {
+ const selectOnchange = (e) => {
dispatch({
type: "SET_ONCHANGE_SERVICE",
- onchangeval: e,
- loader: false
+ loader: false,
+ onChangeValue: e
});
};
- const handleConfirmClick = () => {
- handleDeleteClick();
+ const confirmKeyDelete = () => {
+ handleKeyDelete();
dispatch({
type: "SET_DELETE_MODAL",
- deleteshowmodal: false
+ deleteShowModal: false
});
};
const deleteModal = (name) => {
dispatch({
type: "SET_DELETE_MODAL",
- deleteshowmodal: true,
- filterdata: name
+ deleteShowModal: true,
+ filterData: name
});
};
const editModal = (name) => {
dispatch({
type: "SET_EDIT_MODAL",
- editshowmodal: true,
- filterdata: name
+ editShowModal: true,
+ filterData: name
});
};
const closeEditModal = () => {
dispatch({
type: "SET_EDIT_MODAL_CLOSE",
- editshowmodal: false
+ editShowModal: false
});
};
- const EditConfirmClick = () => {
- handleEditClick();
+ const confirmKeyEdit = () => {
+ handleKeyEdit();
dispatch({
type: "SET_EDIT_MODAL_CLOSE",
- editshowmodal: false
+ editShowModal: false
});
};
- const handleEditClick = useCallback(async () => {
+ const handleKeyEdit = useCallback(async () => {
let keyEdit = {};
- keyEdit.name = filterdata ? filterdata : "";
+ keyEdit.name = filterData ? filterData : "";
try {
- setBlockUI(true);
+ dispatch({ type: "SET_BLOCK_UI", blockUi: true });
await fetchApi({
url: `/keys/key`,
method: "PUT",
- params: { provider: onchangeval ? onchangeval.label : "" },
+ params: { provider: onChangeValue ? onChangeValue.label : "" },
data: keyEdit
});
- setBlockUI(false);
+ dispatch({ type: "SET_BLOCK_UI", blockUi: false });
toast.success(`Success! Key rollover successfully`);
dispatch({
type: "SET_UPDATE_TABLE",
- updatetable: moment.now()
+ updateTable: moment.now()
});
} catch (error) {
- setBlockUI(false);
- let errorMsg = `Error occurred during editing Key` + "\n";
+ dispatch({ type: "SET_BLOCK_UI", blockUi: false });
+ let errorMsg = `Error occurred during editing key` + "\n";
if (error?.response?.data?.msgDesc) {
errorMsg = "Error! " + error.response.data.msgDesc + "\n";
}
toast.error(errorMsg);
- console.error(`Error occurred during editing Key! ${error}`);
+ console.error(`Error occurred during editing key : ${error}`);
}
- }, [filterdata]);
+ }, [filterData]);
- const handleDeleteClick = useCallback(async () => {
+ const handleKeyDelete = useCallback(async () => {
try {
- setBlockUI(true);
+ dispatch({ type: "SET_BLOCK_UI", blockUi: true });
await fetchApi({
- url: `/keys/key/${filterdata}`,
+ url: `/keys/key/${filterData}`,
method: "DELETE",
- params: { provider: onchangeval ? onchangeval.label : "" }
+ params: { provider: onChangeValue ? onChangeValue.label : "" }
});
- setBlockUI(false);
+ dispatch({ type: "SET_BLOCK_UI", blockUi: false });
toast.success(`Success! Key deleted successfully`);
- if (keydata.length == 1 && currentPageIndex > 1) {
+ if (keyData.length == 1 && currentPageIndex > 1) {
if (typeof resetPage?.page === "function") {
resetPage.page(0);
}
} else {
dispatch({
type: "SET_UPDATE_TABLE",
- updatetable: moment.now()
+ updateTable: moment.now()
});
}
} catch (error) {
- setBlockUI(false);
+ dispatch({ type: "SET_BLOCK_UI", blockUi: false });
let errorMsg = "";
if (error?.response?.data?.msgDesc) {
errorMsg = toast.error("Error! " + error.response.data.msgDesc + "\n");
} else {
- errorMsg = `Error occurred during deleting Key` + "\n";
+ errorMsg = `Error occurred during deleting key` + "\n";
}
console.error(errorMsg);
}
- }, [filterdata]);
+ }, [filterData]);
const closeModal = () => {
dispatch({
type: "SET_DELETE_MODAL_CLOSE",
- deleteshowmodal: false
+ deleteShowModal: false
});
};
@@ -350,39 +377,42 @@
type: "SET_LOADER",
loader: true
});
- let selservicesResp = [];
- let selcservicesdata = null;
+ let selectedServicesResponse = [];
+ let selectedServicesData = null;
let totalCount = 0;
let page = pageIndex;
let params = { ...searchFilterParams };
+
params["page"] = page;
params["startIndex"] = pageIndex * pageSize;
params["pageSize"] = pageSize;
- params["provider"] = onchangeval && onchangeval.label;
+ params["provider"] = onChangeValue && onChangeValue.label;
try {
- selservicesResp = await fetchApi({
+ selectedServicesResponse = await fetchApi({
url: "/keys/keys",
params: params
});
- selcservicesdata = selservicesResp.data.vXKeys;
- totalCount = selservicesResp.data.totalCount;
+ selectedServicesData = selectedServicesResponse.data.vXKeys;
+ totalCount = selectedServicesResponse.data.totalCount;
} catch (error) {
let errorMsg = `Error occurred while fetching Services`;
if (error?.response?.data?.msgDesc) {
errorMsg = "Error! " + error.response.data.msgDesc;
}
toast.error(errorMsg);
- console.error(`Error occurred while fetching Services! ${error}`);
+ console.error(`Error occurred while fetching keys : ${error}`);
}
- if (state) {
- state["showLastPage"] = false;
+ if (navigateState) {
+ navigateState["showLastPage"] = false;
}
+
dispatch({
type: "SET_SEL_SERVICE",
- keydatalist: selcservicesdata,
- pagecount: Math.ceil(totalCount / pageSize)
+ keyDataList: selectedServicesData,
+ pageCount: Math.ceil(totalCount / pageSize),
+ totalCount: totalCount
});
dispatch({
type: "SET_CURRENT_PAGE_INDEX",
@@ -400,15 +430,14 @@
type: "SET_LOADER",
loader: false
});
- setTotalCount(totalCount);
},
- [onchangeval, updatetable, searchFilterParams]
+ [onChangeValue, updateTable, refreshTableData]
);
const addKey = () => {
- navigate(`/kms/keys/${onchangeval.label}/create`, {
+ navigate(`/kms/keys/${onChangeValue.label}/create`, {
state: {
- detail: onchangeval.label
+ detail: onChangeValue.label
}
});
};
@@ -524,7 +553,7 @@
width: 80
}
],
- [updatetable]
+ [updateTable]
);
const searchFilterOptions = [
@@ -537,12 +566,17 @@
];
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: "SET_SEARCH_FILTER_PARAMS",
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
};
@@ -554,19 +588,19 @@
</div>
<div className="wrap">
- <BlockUi isUiBlock={blockUI} />
+ <BlockUi isUiBlock={blockUi} />
<Row>
<Col sm={12}>
<div className="formHeader pb-3 mb-3">
Select Service:
<AsyncSelect
- value={onchangeval}
+ value={onChangeValue}
className="w-25"
isClearable
components={{
IndicatorSeparator: () => null
}}
- onChange={selconChange}
+ onChange={selectOnchange}
loadOptions={fetchServices}
placeholder="Please select KMS service"
defaultOptions
@@ -588,8 +622,8 @@
{isKeyAdmin() && (
<Col sm={2} className="text-end">
<Button
- className={onchangeval !== null ? "" : "button-disabled"}
- disabled={onchangeval != null ? false : true}
+ className={onChangeValue !== null ? "" : "button-disabled"}
+ disabled={onChangeValue != null ? false : true}
onClick={addKey}
data-id="addNewKey"
data-cy="addNewKey"
@@ -602,37 +636,37 @@
<XATableLayout
loading={loader}
- data={keydata || []}
+ data={keyData || []}
columns={
isKeyAdmin() ? columns : reject(columns, ["Header", "Action"])
}
fetchData={selectServices}
- pageCount={pagecount}
+ pageCount={pageCount}
currentPageIndex={currentPageIndex}
currentPageSize={currentPageSize}
totalCount={totalCount}
/>
- <Modal show={editshowmodal} onHide={closeEditModal}>
+ <Modal show={editShowModal} onHide={closeEditModal}>
<Modal.Body>{`Are you sure want to rollover ?`}</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={closeEditModal}>
Close
</Button>
- <Button variant="primary" onClick={EditConfirmClick}>
- Ok
+ <Button variant="primary" onClick={confirmKeyEdit}>
+ OK
</Button>
</Modal.Footer>
</Modal>
- <Modal show={deleteshowmodal} onHide={closeModal}>
+ <Modal show={deleteShowModal} onHide={closeModal}>
<Modal.Body>{`Are you sure you want to delete ?`}</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={closeModal}>
Close
</Button>
- <Button variant="primary" onClick={handleConfirmClick}>
- Ok
+ <Button variant="primary" onClick={confirmKeyDelete}>
+ OK
</Button>
</Modal.Footer>
</Modal>
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx
index 8e91429..c8ad8b3 100755
--- a/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/GovernedData/Dataset/DatasetDetailLayout.jsx
@@ -25,39 +25,33 @@
useRef
} from "react";
import withRouter from "Hooks/withRouter";
-import { fetchApi } from "../../../utils/fetchAPI";
+import { fetchApi } from "Utils/fetchAPI";
import dateFormat from "dateformat";
-import XATableLayout from "../../../components/XATableLayout";
-import { ClassTypes } from "../../../utils/XAEnums";
+import XATableLayout from "Components/XATableLayout";
+import { ClassTypes } from "Utils/XAEnums";
import {
Button,
Tab,
Tabs,
Modal,
Accordion,
- Card,
DropdownButton,
Dropdown
} from "react-bootstrap";
-import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import AccessGrantForm from "./AccessGrantForm";
import { toast } from "react-toastify";
import { Form } from "react-final-form";
-import { CustomTooltip, Loader } from "../../../components/CommonComponents";
+import { CustomTooltip, Loader } from "Components/CommonComponents";
import moment from "moment-timezone";
-import {
- useParams,
- useNavigate,
- useLocation,
- useSearchParams
-} from "react-router-dom";
+import { useParams, useNavigate, useLocation } from "react-router-dom";
import {
getTableSortBy,
getTableSortType,
serverError,
isSystemAdmin,
parseSearchFilter
-} from "../../../utils/XAUtils";
+} from "Utils/XAUtils";
import Select from "react-select";
import userColourIcon from "../../../images/user-colour.svg";
import groupColourIcon from "../../../images/group-colour.svg";
@@ -67,10 +61,10 @@
import { groupBy, isEmpty, isArray } from "lodash";
import PrinciplePermissionComp from "./PrinciplePermissionComp";
import ReactPaginate from "react-paginate";
-import CustomBreadcrumb from "../../CustomBreadcrumb";
-import ErrorPage from "../../../views/ErrorPage";
+import CustomBreadcrumb from "Views/CustomBreadcrumb";
+import ErrorPage from "Views/ErrorPage";
import DatashareInDatasetListComp from "./DatashareInDatasetListComp";
-import OperationAdminModal from "../../AuditEvent/OperationAdminModal";
+import OperationAdminModal from "Views/AuditEvent/Admin/OperationAdminModal";
const initialState = {
loader: false,
@@ -816,10 +810,6 @@
})
};
- const dropDownStyle = {
- control: (provided) => ({ ...provided, display: none })
- };
-
const onChangeSharedWithPrincipleName = (event) => {
setSharedWithPrincipleName(event.target.value);
filterSharedWithPrincipleList(event.target.value, true, undefined, false);
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 6590cb7..dd0a0d6 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
@@ -17,29 +17,15 @@
* under the License.
*/
-import React, {
- useState,
- useEffect,
- useRef,
- useCallback,
- useReducer
-} from "react";
-import {
- useParams,
- useNavigate,
- Link,
- useLocation,
- useSearchParams
-} from "react-router-dom";
-import { fetchApi } from "../../../utils/fetchAPI";
-import { Loader } from "../../../components/CommonComponents";
-import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
+import React, { useState, useEffect, useRef, useCallback } from "react";
+import { useParams, useNavigate, useLocation } from "react-router-dom";
+import { fetchApi } from "Utils/fetchAPI";
+import { Loader } from "Components/CommonComponents";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import {
Button,
Col,
Modal,
- Accordion,
- Card,
Tab,
Tabs,
DropdownButton,
@@ -47,14 +33,13 @@
} from "react-bootstrap";
import dateFormat from "dateformat";
import { toast } from "react-toastify";
-import { BlockUi } from "../../../components/CommonComponents";
+import { BlockUi } from "Components/CommonComponents";
import PrinciplePermissionComp from "../Dataset/PrinciplePermissionComp";
import { Form, Field } from "react-final-form";
import arrayMutators from "final-form-arrays";
-import ReactPaginate from "react-paginate";
import AddSharedResourceComp from "./AddSharedResourceComp";
-import CustomBreadcrumb from "../../CustomBreadcrumb";
-import PolicyConditionsComp from "../../PolicyListing/PolicyConditionsComp";
+import CustomBreadcrumb from "Views/CustomBreadcrumb";
+import PolicyConditionsComp from "Views/PolicyListing/PolicyConditionsComp";
import {
getTableSortBy,
getTableSortType,
@@ -63,16 +48,16 @@
serverError,
policyConditionUpdatedJSON,
capitalizeFirstLetter
-} from "../../../utils/XAUtils";
-import XATableLayout from "../../../components/XATableLayout";
+} from "Utils/XAUtils";
+import XATableLayout from "Components/XATableLayout";
import moment from "moment-timezone";
-import { getServiceDef } from "../../../utils/appState";
+import { getServiceDef } from "Utils/appState";
import DatashareInDatasetListComp from "../Dataset/DatashareInDatasetListComp";
-import { isEmpty, isObject, isEqual } from "lodash";
+import { isObject, isEqual } from "lodash";
import Select from "react-select";
-import OperationAdminModal from "../../AuditEvent/OperationAdminModal";
+import OperationAdminModal from "Views/AuditEvent/Admin/OperationAdminModal";
import historyDetailsIcon from "../../../images/history-details.svg";
-import { ClassTypes } from "../../../utils/XAEnums";
+import { ClassTypes } from "Utils/XAEnums";
const DatashareDetailLayout = () => {
let { datashareId } = useParams();
@@ -178,7 +163,7 @@
setLoader(false);
let resp = [];
let params = { ...searchFilterParams };
- params["dataShareId"] = dataShareId;
+ params["dataShareId"] = datashareId;
try {
resp = await fetchApi({
url: "gds/datashare/summary",
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/Permissions.jsx b/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/Permissions.jsx
index 73c22bc..ab85e8c 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/Permissions.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/Permissions.jsx
@@ -17,32 +17,26 @@
* under the License.
*/
-import React, { useState, useRef, useCallback, useEffect } from "react";
+import React, { useState, useCallback, useEffect, useReducer } from "react";
import { Row, Col } from "react-bootstrap";
-import { Link, useSearchParams } from "react-router-dom";
-import XATableLayout from "Components/XATableLayout";
-import { isSystemAdmin, isKeyAdmin } from "Utils/XAUtils";
-import { MoreLess } from "Components/CommonComponents";
+import { Link, useSearchParams, useLocation } from "react-router-dom";
import { isEmpty, reject, find, isUndefined, sortBy } from "lodash";
+import moment from "moment-timezone";
+import XATableLayout from "Components/XATableLayout";
+import { isSystemAdmin, isKeyAdmin, parseSearchFilter } from "Utils/XAUtils";
+import { Loader, MoreLess } from "Components/CommonComponents";
import { fetchApi } from "Utils/fetchAPI";
-import { commonBreadcrumb, parseSearchFilter } from "../../utils/XAUtils";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
-import { Loader } from "../../components/CommonComponents";
-import CustomBreadcrumb from "../CustomBreadcrumb";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
+import { ACTIONS } from "./action";
+import { reducer, INITIAL_STATE } from "./reducer";
function Permissions() {
- const [permissionslistData, setPermissions] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageLoader, setPageLoader] = useState(true);
- const [pageCount, setPageCount] = React.useState(0);
- const [totalCount, setTotalCount] = useState(0);
- const fetchIdRef = useRef(0);
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
+
+ const location = useLocation();
+
const [isAdminRole] = useState(isSystemAdmin() || isKeyAdmin());
- const [searchFilterParams, setSearchFilterParams] = useState([]);
const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
useEffect(() => {
let searchFilterParam = {};
@@ -51,6 +45,7 @@
// Get Search Filter Params from current search params
const currentParams = Object.fromEntries([...searchParams]);
+
for (const param in currentParams) {
let searchFilterObj = find(searchFilterOptions, {
urlLabel: param
@@ -78,41 +73,56 @@
// Updating the states for search params, search filter and default search filter
setSearchParams({ ...currentParams, ...searchParam }, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- setPageLoader(false);
- }, [searchParams]);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ }, [location.search]);
const fetchPermissions = useCallback(
async ({ pageSize, pageIndex }) => {
- setLoader(true);
- let permissionsdata = [];
- let totalCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["pageSize"] = pageSize;
- params["startIndex"] = pageIndex * pageSize;
- try {
- const permissionResp = await fetchApi({
- url: "xusers/permission",
- params: params
- });
- permissionsdata = permissionResp.data.vXModuleDef;
- totalCount = permissionResp.data.totalCount;
- } catch (error) {
- console.error(`Error occurred while fetching Group list! ${error}`);
- }
- setPermissions(permissionsdata);
- setTotalCount(totalCount);
- setPageCount(Math.ceil(totalCount / pageSize));
- setLoader(false);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+
+ const params = {
+ ...state.searchFilterParams,
+ pageSize,
+ startIndex: pageIndex * pageSize
+ };
+
+ try {
+ const response = await fetchApi({
+ url: "xusers/permission",
+ params: params
+ });
+
+ const permissionsData = response.data?.vXModuleDef || [];
+ const totalCount = response.data?.totalCount || 0;
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: permissionsData,
+ pageCount: Math.ceil(totalCount / pageSize),
+ totalCount: totalCount
+ });
+ } catch (error) {
+ console.error(
+ `Error occurred while fetching users permission ! ${error}`
+ );
}
+
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [searchFilterParams]
+ [state.refreshTableData]
);
const columns = React.useMemo(
@@ -140,7 +150,6 @@
},
{
Header: "Groups",
- accessor: "groupPermList",
accessor: (raw) => {
const Groups = raw.groupPermList.map((group) => {
return group.groupName;
@@ -155,7 +164,6 @@
},
{
Header: "Users",
- accessor: "userPermList",
accessor: (raw) => {
const Users = raw.userPermList.map((user) => {
return user.userName;
@@ -211,23 +219,27 @@
];
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
};
return (
- <>
+ <React.Fragment>
<div className="header-wraper">
<h3 className="wrap-header bold">Permissions</h3>
- <CustomBreadcrumb />
</div>
<div className="wrap">
- {pageLoader ? (
+ {state.contentLoader ? (
<Loader />
) : (
<React.Fragment>
@@ -238,24 +250,25 @@
placeholder="Search for permissions..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</Col>
</Row>
+
<XATableLayout
- data={permissionslistData}
+ data={state.tableListingData}
columns={
isAdminRole ? columns : reject(columns, ["Header", "Action"])
}
- totalCount={totalCount}
- loading={loader}
+ totalCount={state.totalCount}
+ loading={state.loader}
fetchData={fetchPermissions}
- pageCount={pageCount}
+ pageCount={state.pageCount}
/>
</React.Fragment>
)}
</div>
- </>
+ </React.Fragment>
);
}
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/action.js b/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/action.js
new file mode 100644
index 0000000..00f7496
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/action.js
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ */
+
+export const ACTIONS = {
+ SET_TABLE_LOADER: "set-table-loader",
+ SET_CONTENT_LOADER: "set-content-loader",
+ SET_SEARCH_FILTER_PARAMS: "set-search-filter-params",
+ SET_DEFAULT_SEARCH_FILTER_PARAMS: "set-default-search-filter-params",
+ SET_TABLE_DATA: "set-table-data"
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/reducer.js b/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/reducer.js
new file mode 100644
index 0000000..1344f01
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/PermissionsModule/reducer.js
@@ -0,0 +1,67 @@
+/*
+ * 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 moment from "moment-timezone";
+import { ACTIONS } from "./action";
+
+export const INITIAL_STATE = {
+ loader: true,
+ contentLoader: true,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ tableListingData: [],
+ pageCount: 0,
+ totalCount: 0,
+ refreshTableData: moment.now()
+};
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.SET_TABLE_LOADER:
+ return {
+ ...state,
+ loader: action.loader
+ };
+ case ACTIONS.SET_CONTENT_LOADER:
+ return {
+ ...state,
+ contentLoader: action.contentLoader
+ };
+ case ACTIONS.SET_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case ACTIONS.SET_TABLE_DATA:
+ return {
+ ...state,
+ tableListingData: action.tableListingData,
+ pageCount: action.pageCount,
+ totalCount: action.totalCount
+ };
+ default:
+ return state;
+ }
+};
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 e6b2825..515c2b0 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
@@ -62,19 +62,20 @@
import { useParams, useNavigate, useLocation } from "react-router-dom";
import PolicyValidityPeriodComp from "./PolicyValidityPeriodComp";
import PolicyConditionsComp from "./PolicyConditionsComp";
-import { getAllTimeZoneList, policyConditionUpdatedJSON } from "Utils/XAUtils";
import moment from "moment";
import {
InfoIcon,
commonBreadcrumb,
isPolicyExpired,
- getResourcesDefVal
+ getResourcesDefVal,
+ getAllTimeZoneList,
+ policyConditionUpdatedJSON,
+ policyInfo
} from "Utils/XAUtils";
import { useAccordionButton } from "react-bootstrap/AccordionButton";
import AccordionContext from "react-bootstrap/AccordionContext";
import usePrompt from "Hooks/usePrompt";
import { RegexMessage } from "Utils/XAMessages";
-import { policyInfo } from "Utils/XAUtils";
import { getServiceDef } from "Utils/appState";
import { FieldArray } from "react-final-form-arrays";
@@ -926,14 +927,17 @@
method: "POST",
data
});
- let tblpageData = {};
+ let tablePageData = {};
if (state && state != null) {
- tblpageData = state.tblpageData;
- if (state.tblpageData.pageRecords % state.tblpageData.pageSize == 0) {
- tblpageData["totalPage"] = state.tblpageData.totalPage + 1;
+ tablePageData = state.tablePageData;
+ if (
+ state.tablePageData.pageRecords % state.tablePageData.pageSize ==
+ 0
+ ) {
+ tablePageData["totalPage"] = state.tablePageData.totalPage + 1;
} else {
- if (tblpageData !== undefined) {
- tblpageData["totalPage"] = state.tblpageData.totalPage;
+ if (tablePageData !== undefined) {
+ tablePageData["totalPage"] = state.tablePageData.totalPage;
}
}
}
@@ -943,7 +947,7 @@
navigate(`/service/${serviceId}/policies/${policyType}`, {
state: {
showLastPage: true,
- addPageData: tblpageData
+ addPageData: tablePageData
}
});
} catch (error) {
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 a32035e..63cc3a0 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
@@ -17,8 +17,7 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
-import { omit, has } from "lodash";
+import React, { useCallback, useEffect, useReducer } from "react";
import {
Link,
useParams,
@@ -30,8 +29,6 @@
import moment from "moment-timezone";
import { toast } from "react-toastify";
import {
- pick,
- indexOf,
isUndefined,
isEmpty,
map,
@@ -39,18 +36,13 @@
find,
concat,
camelCase,
- union
+ union,
+ omit,
+ has
} from "lodash";
import { fetchApi } from "Utils/fetchAPI";
import XATableLayout from "Components/XATableLayout";
-import {
- showGroupsOrUsersOrRolesForPolicy,
- QueryParamsName
-} from "Utils/XAUtils";
-import { MoreLess, scrollToNewData } from "Components/CommonComponents";
-import {} from "Utils/XAUtils";
-import PolicyViewDetails from "../AuditEvent/AdminLogs/PolicyViewDetails";
-import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
import {
isAuditor,
isKMSAuditor,
@@ -59,122 +51,67 @@
isKeyAdmin,
isUser,
parseSearchFilter,
- getResourcesDefVal
-} from "../../utils/XAUtils";
+ getResourcesDefVal,
+ showGroupsOrUsersOrRolesForPolicy,
+ QueryParamsName
+} from "Utils/XAUtils";
import {
alertMessage,
ResourcesOverrideInfoMsg,
ServerAttrName
-} from "../../utils/XAEnums";
+} from "Utils/XAEnums";
import {
BlockUi,
CustomPopover,
- Loader
-} from "../../components/CommonComponents";
+ Loader,
+ MoreLess,
+ scrollToNewData
+} from "Components/CommonComponents";
+import AccessLogPolicyModal from "Views/AuditEvent/Access/AccessLogPolicyModal";
+import { ACTIONS } from "./action";
+import { reducer, INITIAL_STATE } from "./reducer";
function PolicyListing(props) {
const { serviceDef, serviceData, serviceZone } = props;
- const { state } = useLocation();
- const [policyListingData, setPolicyData] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageCount, setPageCount] = useState(
- state && state.showLastPage ? state.addPageData.totalPage : 0
- );
- const [currentpageIndex, setCurrentPageIndex] = useState(
- state && state.showLastPage ? state.addPageData.totalPage - 1 : 0
- );
- const [currentpageSize, setCurrentPageSize] = useState(
- state && state.showLastPage ? state.addPageData.pageSize : 25
- );
- const [totalCount, setTotalCount] = useState(0);
- const [tblpageData, setTblPageData] = useState({
- totalPage: 0,
- pageRecords: 0,
- pageSize: 25
- });
- const fetchIdRef = useRef(0);
- const [deletePolicyModal, setConfirmModal] = useState({
- policyDetails: {},
- showSyncDetails: false
- });
- const [policyviewmodal, setPolicyViewModal] = useState(false);
- const [policyParamsData, setPolicyParamsData] = useState(null);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [currentPage, setCurrentPage] = useState(1);
- const [searchFilterParams, setSearchFilterParams] = useState([]);
+ const navigate = useNavigate();
+ const { state: navigateState, search } = useLocation();
+ const { serviceId, policyType } = useParams();
+
+ let initialArg = { navigateState: navigateState };
+
+ const [state, dispatch] = useReducer(reducer, initialArg, INITIAL_STATE);
+
const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [pageLoader, setPageLoader] = useState(true);
- const [resetPage, setResetpage] = useState({ page: 0 });
- const [show, setShow] = useState(true);
- const [blockUI, setBlockUI] = useState(false);
- let navigate = useNavigate();
- let { serviceId, policyType } = useParams();
- const [showModal, setShowModal] = useState(false);
- const [selectedFile, setSelectedFile] = useState(null);
- const [statusMessage, setStatusMessage] = useState("");
- const [loading, setLoading] = useState(false);
-
- const handleFileSelection = (event) => {
+ const handlePolicyImportFile = (event) => {
const file = event.target.files[0];
- setSelectedFile(file); // Store selected file
- setStatusMessage("");
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: state.showImportPolicyModal,
+ importPolicyFile: file,
+ importPolicyStatusMsg: [],
+ importPolicyLoading: false
+ });
};
const importNewPolicy = () => {
- setShowModal(true); // Show the modal when button is clicked
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: true,
+ importPolicyFile: null,
+ importPolicyStatusMsg: [],
+ importPolicyLoading: false
+ });
};
- const handleCloseModal = () => {
- setSelectedFile(null); // Reset the selected file
- setStatusMessage("");
- setShowModal(false);
- };
-
- const handleUpload = () => {
- if (!selectedFile) {
- setStatusMessage("No file selected !");
- return;
- }
-
- const reader = new FileReader();
- reader.onload = async (e) => {
- try {
- const json = JSON.parse(e.target.result);
-
- if (has("service")) {
- json["service"] = serviceData.name;
- }
-
- // Make API call with the processed JSON
- setLoading(true); // Show loading spinner
- await fetchApi({
- url: "plugins/policies",
- method: "POST",
- headers: {
- "Content-Type": "application/json" // Set Content-Type header
- },
- data: JSON.stringify(json) // Serialize the JSON
- });
-
- setLoading(false); // Hide loading spinner
- setStatusMessage("");
- setShowModal(false);
- setUpdateTable(moment.now());
- toast.success("Successfully imported policy json file !");
- } catch (error) {
- setLoading(false);
- setStatusMessage(
- `Error parsing or processing JSON file: ${error.message}`
- );
- console.log(error);
- }
- };
-
- reader.readAsText(selectedFile);
+ const closePolicyImportModal = () => {
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: false,
+ importPolicyFile: null,
+ importPolicyStatusMsg: [],
+ importPolicyLoading: false
+ });
};
useEffect(() => {
@@ -211,30 +148,108 @@
// Updating the states for search params, search filter and default search filter
setSearchParams({ ...currentParams, ...searchParam }, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- setPageLoader(false);
- localStorage.setItem("newDataAdded", state && state.showLastPage);
- }, [searchParams]);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ localStorage.setItem(
+ "newDataAdded",
+ navigateState && navigateState.showLastPage
+ );
+ }, [search]);
useEffect(() => {
if (localStorage.getItem("newDataAdded") == "true") {
- scrollToNewData(policyListingData);
+ scrollToNewData(state.tableListingData);
}
- }, [totalCount]);
- const getTableSortBy = (sortArr = []) => {
- return sortArr
- .map(({ id }) => {
- return QueryParamsName(id);
- })
- .join(",");
- };
+ }, [state.totalCount]);
- const getTableSortType = (sortArr = []) => {
- return sortArr.map(({ desc }) => (desc ? "desc" : "asc")).join(",");
+ const handlePolicyUpload = () => {
+ if (!state.importPolicyFile) {
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: state.showImportPolicyModal,
+ importPolicyFile: state.importPolicyFile,
+ importPolicyStatusMsg: [
+ <p className="fw-bold" key="upload-no-file">
+ No file selected !
+ </p>
+ ],
+ importPolicyLoading: false
+ });
+ return;
+ }
+
+ const reader = new FileReader();
+ reader.onload = async (e) => {
+ try {
+ const json = JSON.parse(e.target.result);
+
+ if (has("service")) {
+ json["service"] = serviceData.name;
+ }
+
+ // Make API call with the processed JSON
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: state.showImportPolicyModal,
+ importPolicyFile: state.importPolicyFile,
+ importPolicyStatusMsg: state.importPolicyStatusMsg,
+ importPolicyLoading: true
+ });
+ await fetchApi({
+ url: "plugins/policies",
+ method: "POST",
+ headers: {
+ "Content-Type": "application/json" // Set Content-Type header
+ },
+ data: JSON.stringify(json) // Serialize the JSON
+ });
+
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: false,
+ importPolicyFile: state.importPolicyFile,
+ importPolicyStatusMsg: [],
+ importPolicyLoading: false
+ });
+ refreshTable();
+ toast.success("Successfully imported policy json file !");
+ } catch (error) {
+ let errorMsg = [
+ <p className="fw-bold" key="upload-error">
+ Error parsing or processing JSON file: {error.message}
+ </p>
+ ];
+ if (error?.response?.data?.msgDesc) {
+ errorMsg.push([
+ <p className="connection-error" key="upload-error-message">
+ {error.response.data.msgDesc}
+ </p>
+ ]);
+ }
+ dispatch({
+ type: ACTIONS.IMPORT_POLICY,
+ showImportPolicyModal: state.showImportPolicyModal,
+ importPolicyFile: state.importPolicyFile,
+ importPolicyStatusMsg: errorMsg,
+ importPolicyLoading: false
+ });
+ console.log(error);
+ }
+ };
+
+ reader.readAsText(state.importPolicyFile);
};
const downloadPolicy = async (id) => {
@@ -296,123 +311,98 @@
}
};
- const fetchPolicyInfo = useCallback(
+ const fetchPolicies = useCallback(
async ({ pageSize, pageIndex, sortBy, gotoPage }) => {
- setLoader(true);
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
let policyData = [];
- let policyResp = [];
let totalCount = 0;
let page =
- state && state.showLastPage
- ? state.addPageData.totalPage - 1
+ navigateState && navigateState.showLastPage
+ ? navigateState.addPageData.totalPage - 1
: pageIndex;
let totalPageCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["page"] = page;
- params["startIndex"] =
- state && state.showLastPage
- ? (state.addPageData.totalPage - 1) * pageSize
- : pageIndex * pageSize;
- params["pageSize"] = pageSize;
- params["policyType"] = policyType;
- if (sortBy.length > 0) {
- params["sortBy"] = getTableSortBy(sortBy);
- params["sortType"] = getTableSortType(sortBy);
- }
+ let params = { ...state.searchFilterParams };
- if (serviceZone !== null) {
- params["zoneName"] = serviceZone.label;
- }
- try {
- policyResp = await fetchApi({
- url: `plugins/policies/service/${serviceId}`,
- params: params
- });
- policyData = policyResp.data.policies;
- totalCount = policyResp.data.totalCount;
- totalPageCount = Math.ceil(totalCount / pageSize);
- } catch (error) {
- console.error(`Error occurred while fetching Policies ! ${error}`);
- }
- if (state) {
- state["showLastPage"] = false;
- }
- setPolicyData(policyData);
- setTblPageData({
- totalPage: totalPageCount,
- pageRecords: policyResp?.data?.totalCount,
- pageSize: 25
- });
- setTotalCount(totalCount);
- setPageCount(totalPageCount);
- setCurrentPageIndex(page);
- setCurrentPageSize(pageSize);
- setResetpage({ page: gotoPage });
- setLoader(false);
+ params["page"] = page;
+ params["startIndex"] =
+ navigateState && navigateState.showLastPage
+ ? (navigateState.addPageData.totalPage - 1) * pageSize
+ : pageIndex * pageSize;
+ params["pageSize"] = pageSize;
+ params["policyType"] = policyType;
+
+ if (sortBy.length > 0) {
+ params["sortBy"] = getTableSortBy(sortBy);
+ params["sortType"] = getTableSortType(sortBy);
}
+
+ if (serviceZone !== null) {
+ params["zoneName"] = serviceZone.label;
+ }
+
+ try {
+ const response = await fetchApi({
+ url: `plugins/policies/service/${serviceId}`,
+ params: params
+ });
+ policyData = response.data?.policies || [];
+ totalCount = response.data?.totalCount || 0;
+ totalPageCount = Math.ceil(totalCount / pageSize);
+ } catch (error) {
+ console.error(`Error occurred while fetching policies : ${error}`);
+ }
+
+ if (navigateState) {
+ navigateState["showLastPage"] = false;
+ }
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: policyData,
+ totalCount: totalCount,
+ pageCount: totalPageCount,
+ currentPageIndex: page,
+ currentPageSize: pageSize,
+ resetPage: { page: gotoPage },
+ tablePageData: {
+ totalPage: totalPageCount,
+ pageRecords: totalCount,
+ pageSize: pageSize
+ }
+ });
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
- const toggleConfirmModalForDelete = (policyID, policyName) => {
- setConfirmModal({
- policyDetails: { policyID: policyID, policyName: policyName },
- showPopup: true
+ const policyDelete = (policyId, policyName) => {
+ dispatch({
+ type: ACTIONS.SHOW_DELETE_MODAL,
+ showDeleteModal: true,
+ policyDetail: { policyId: policyId, policyName: policyName }
});
};
- const toggleClose = () => {
- setConfirmModal({
- policyDetails: {},
- showPopup: false
+ const togglePolicyDeleteModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_DELETE_MODAL,
+ showDeleteModal: false,
+ policyDetail: { policyId: "", policyName: "" }
});
};
- const handleClosePolicyId = () => setPolicyViewModal(false);
-
- const openModal = (policyDetails) => {
- let policyId = pick(policyDetails, ["id"]);
- setPolicyViewModal(true);
- setPolicyParamsData(policyDetails);
- fetchVersions(policyId.id);
- };
-
- const fetchVersions = async (policyId) => {
- let versionsResp = {};
+ const handlePolicyDelete = async (policyId) => {
+ togglePolicyDeleteModal();
try {
- versionsResp = await fetchApi({
- url: `plugins/policy/${policyId}/versionList`
- });
- } catch (error) {
- console.error(
- `Error occurred while fetching Policy Version or CSRF headers! ${error}`
- );
- }
- setCurrentPage(
- versionsResp.data.value
- .split(",")
- .map(Number)
- .sort(function (a, b) {
- return a - b;
- })
- );
- setLoader(false);
- };
-
- const handleDeleteClick = async (policyID) => {
- toggleClose();
- try {
- setBlockUI(true);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: true });
await fetchApi({
- url: `plugins/policies/${policyID}`,
+ url: `plugins/policies/${policyId}`,
method: "DELETE"
});
- setBlockUI(false);
- toast.success(" Success! Policy deleted successfully");
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
+ toast.success("Policy deleted successfully !");
} catch (error) {
- setBlockUI(false);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
let errorMsg = "Failed to delete policy : ";
if (error?.response?.data?.msgDesc) {
errorMsg += error.response.data.msgDesc;
@@ -420,61 +410,62 @@
toast.error(errorMsg);
console.error("Error occurred during deleting policy : " + error);
}
- if (policyListingData.length == 1 && currentpageIndex > 0) {
- let page = currentpageIndex - currentpageIndex;
- if (typeof resetPage?.page === "function") {
- resetPage.page(page);
+ if (state.tableListingData.length == 1 && state.currentPageIndex > 0) {
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
} else {
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
}
};
- const previousVersion = (e) => {
- if (e.currentTarget.classList.contains("active")) {
- let curr = policyParamsData && policyParamsData.version;
- let policyVersionList = currentPage;
- var previousVal =
- policyVersionList[
- (indexOf(policyVersionList, curr) - 1) % policyVersionList.length
- ];
- }
- let prevVal = {};
- prevVal.version = previousVal;
- prevVal.id = policyParamsData.id;
- prevVal.isChangeVersion = true;
- setPolicyParamsData(prevVal);
+ const hidePolicyModal = () =>
+ dispatch({
+ type: ACTIONS.SHOW_POLICY_MODAL,
+ showPolicyModal: false,
+ policyData: null
+ });
+
+ const openPolicyModal = (policy) => {
+ let policyParams = {
+ policyId: policy.id,
+ policyVersion: policy.version
+ };
+ dispatch({
+ type: ACTIONS.SHOW_POLICY_MODAL,
+ showPolicyModal: true,
+ policyData: policyParams
+ });
};
- const nextVersion = (e) => {
- if (e.currentTarget.classList.contains("active")) {
- let curr = policyParamsData && policyParamsData.version;
- let policyVersionList = currentPage;
- var nextValue =
- policyVersionList[
- (indexOf(policyVersionList, curr) + 1) % policyVersionList.length
- ];
- }
- let nextVal = {};
- nextVal.version = nextValue;
- nextVal.id = policyParamsData.id;
- nextVal.isChangeVersion = true;
- setPolicyParamsData(nextVal);
+ const refreshTable = () => {
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
};
- const revert = (e) => {
- e.preventDefault();
- let version = policyParamsData && policyParamsData.version;
- let revertVal = {};
- revertVal.version = version;
- revertVal.id = policyParamsData.id;
- revertVal.isRevert = true;
- setPolicyParamsData(revertVal);
- setPolicyViewModal(false);
+ const getTableSortBy = (sortArr = []) => {
+ return sortArr
+ .map(({ id }) => {
+ return QueryParamsName(id);
+ })
+ .join(",");
};
- const updateServices = () => {
- setUpdateTable(moment.now());
+ const getTableSortType = (sortArr = []) => {
+ return sortArr.map(({ desc }) => (desc ? "desc" : "asc")).join(",");
+ };
+
+ const addPolicy = () => {
+ navigate(`/service/${serviceId}/policies/create/${policyType}`, {
+ state: { tablePageData: state.tablePageData }
+ });
};
const columns = React.useMemo(
@@ -675,7 +666,7 @@
title="View"
onClick={(e) => {
e.stopPropagation();
- openModal(original);
+ openPolicyModal(original);
}}
data-name="viewPolicy"
data-id={original.id}
@@ -707,9 +698,7 @@
variant="danger"
size="sm"
title="Delete"
- onClick={() =>
- toggleConfirmModalForDelete(original.id, original.name)
- }
+ onClick={() => policyDelete(original.id, original.name)}
data-name="deletePolicy"
data-id={original.id}
data-cy={original.id}
@@ -728,12 +717,6 @@
[]
);
- const addPolicy = () => {
- navigate(`/service/${serviceId}/policies/create/${policyType}`, {
- state: { tblpageData: tblpageData }
- });
- };
-
const searchFilterOptions = [
{
category: "group",
@@ -849,28 +832,40 @@
};
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
getSearchFilterOptions()
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
return (
<div className="wrap">
- {(serviceData.type == "hdfs" || serviceData.type == "yarn") && show && (
- <Alert variant="warning" onClose={() => setShow(false)} dismissible>
- <i className="fa-fw fa fa-info-circle d-inline text-dark"></i>
- <p className="pd-l-10 d-inline">
- {`By default, fallback to ${
- alertMessage[serviceData.type].label
- } ACLs are enabled. If access cannot be
+ {(serviceData.type == "hdfs" || serviceData.type == "yarn") &&
+ state.showAlert && (
+ <Alert
+ variant="warning"
+ onClose={() =>
+ dispatch({ type: ACTIONS.SHOW_ALERT, showAlert: false })
+ }
+ dismissible
+ >
+ <i className="fa-fw fa fa-info-circle d-inline text-dark"></i>
+ <p className="pd-l-10 d-inline">
+ {`By default, fallback to ${
+ alertMessage[serviceData.type].label
+ } ACLs are enabled. If access cannot be
determined by Ranger policies, authorization will fall back to
${
alertMessage[serviceData.type].label
@@ -880,14 +875,14 @@
plugin config - ${
alertMessage[serviceData.type].configs
}-authorization.`}
- </p>
- </Alert>
- )}
- {pageLoader ? (
+ </p>
+ </Alert>
+ )}
+ {state.contentLoader ? (
<Loader />
) : (
<React.Fragment>
- <BlockUi isUiBlock={blockUI} />
+ <BlockUi isUiBlock={state.blockUi} />
<div className="policy-listing">
<Row className="mb-3">
<Col sm={9}>
@@ -897,7 +892,7 @@
placeholder="Search for your policy..."
options={getSearchFilterOptions()}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
<CustomPopover
icon="fa-fw fa fa-info-circle info-icon"
@@ -943,143 +938,87 @@
</Row>
<XATableLayout
- data={policyListingData}
+ data={state.tableListingData}
columns={columns}
- fetchData={fetchPolicyInfo}
- totalCount={totalCount}
+ fetchData={fetchPolicies}
+ totalCount={state.totalCount}
pagination
- pageCount={pageCount}
- currentpageIndex={currentpageIndex}
- currentpageSize={currentpageSize}
- loading={loader}
+ pageCount={state.pageCount}
+ currentpageIndex={state.currentPageIndex}
+ currentpageSize={state.currentPageSize}
+ loading={state.loader}
columnSort={true}
/>
</div>
- {/* Modal for file upload */}
- {showModal && (
- <Modal show={showModal} onHide={handleCloseModal}>
- <Modal.Header closeButton>
- <Modal.Title>Upload JSON Policy</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- <input
- type="file"
- accept="application/json"
- onChange={handleFileSelection}
- />
- {loading && <p>Uploading...</p>}
- {!loading && statusMessage && <p>{statusMessage}</p>}
- </Modal.Body>
- <Modal.Footer>
- <Button
- size="sm"
- variant="secondary"
- onClick={handleCloseModal}
- >
- Close
- </Button>
- <Button size="sm" variant="primary" onClick={handleUpload}>
- Upload
- </Button>
- </Modal.Footer>
- </Modal>
- )}
+ <Modal
+ show={state.showImportPolicyModal}
+ onHide={closePolicyImportModal}
+ >
+ <Modal.Header closeButton>
+ <Modal.Title>Upload JSON Policy</Modal.Title>
+ </Modal.Header>
+ <Modal.Body>
+ <input
+ type="file"
+ accept="application/json"
+ onChange={handlePolicyImportFile}
+ />
+ {state.importPolicyLoading && (
+ <p className="mt-2 fw-bold">Uploading...</p>
+ )}
+ {!state.importPolicyLoading &&
+ state.importPolicyStatusMsg.length > 0 && (
+ <div className="mt-2">{state.importPolicyStatusMsg}</div>
+ )}
+ </Modal.Body>
+ <Modal.Footer>
+ <Button
+ size="sm"
+ variant="secondary"
+ onClick={closePolicyImportModal}
+ >
+ Close
+ </Button>
+ <Button size="sm" variant="primary" onClick={handlePolicyUpload}>
+ Upload
+ </Button>
+ </Modal.Footer>
+ </Modal>
- <Modal show={deletePolicyModal.showPopup} onHide={toggleClose}>
+ <Modal show={state.showDeleteModal} onHide={togglePolicyDeleteModal}>
<Modal.Header closeButton>
<span className="text-word-break">
Are you sure you want to delete policy "
- <b>{deletePolicyModal?.policyDetails?.policyName}</b>" ?
+ <b>{state.policyDetail.policyName}</b>" ?
</span>
</Modal.Header>
<Modal.Footer>
- <Button variant="secondary" size="sm" onClick={toggleClose}>
+ <Button
+ variant="secondary"
+ size="sm"
+ onClick={togglePolicyDeleteModal}
+ >
Close
</Button>
<Button
variant="primary"
size="sm"
- onClick={() =>
- handleDeleteClick(deletePolicyModal.policyDetails.policyID)
- }
+ onClick={() => handlePolicyDelete(state.policyDetail.policyId)}
>
OK
</Button>
</Modal.Footer>
</Modal>
- <Modal show={policyviewmodal} onHide={handleClosePolicyId} size="xl">
- <Modal.Header closeButton>
- <Modal.Title>Policy Details</Modal.Title>
- </Modal.Header>
- <Modal.Body>
- <PolicyViewDetails
- paramsData={policyParamsData}
- policyInfo={fetchPolicyInfo}
- totalCount={totalCount}
- policyView={true}
- updateServices={updateServices}
- />
- </Modal.Body>
- <Modal.Footer>
- <div className="policy-version text-start">
- <span>
- <i
- className={
- policyParamsData && policyParamsData.version > 1
- ? "fa-fw fa fa-chevron-left active"
- : "fa-fw fa fa-chevron-left"
- }
- onClick={(e) =>
- e.currentTarget.classList.contains("active") &&
- previousVersion(e)
- }
- ></i>
- <span>{`Version ${
- policyParamsData && policyParamsData.version
- }`}</span>
- <i
- className={
- !isUndefined(
- currentPage[
- indexOf(
- currentPage,
- policyParamsData && policyParamsData.version
- ) + 1
- ]
- )
- ? "fa-fw fa fa-chevron-right active"
- : "fa-fw fa fa-chevron-right"
- }
- onClick={(e) =>
- e.currentTarget.classList.contains("active") &&
- nextVersion(e)
- }
- ></i>
- </span>
- {!isUndefined(
- currentPage[
- indexOf(
- currentPage,
- policyParamsData && policyParamsData.version
- ) + 1
- ]
- ) && (
- <Button
- variant="primary"
- size="sm"
- onClick={(e) => revert(e)}
- >
- Revert
- </Button>
- )}
- </div>
- <Button variant="primary" size="sm" onClick={handleClosePolicyId}>
- OK
- </Button>
- </Modal.Footer>
- </Modal>
+ <AccessLogPolicyModal
+ policyData={state.policyData}
+ policyView={true}
+ policyRevert={true}
+ refreshTable={refreshTable}
+ showPolicyModal={state.showPolicyModal}
+ hidePolicyModal={hidePolicyModal}
+ ></AccessLogPolicyModal>
</React.Fragment>
)}
</div>
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/action.js b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/action.js
new file mode 100644
index 0000000..f5dcf2a
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/action.js
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+
+export const ACTIONS = {
+ SET_TABLE_LOADER: "set-table-loader",
+ SET_CONTENT_LOADER: "set-content-loader",
+ SET_SEARCH_FILTER_PARAMS: "set-search-filter-params",
+ SET_DEFAULT_SEARCH_FILTER_PARAMS: "set-default-search-filter-params",
+ SET_TABLE_DATA: "set-table-data",
+ SHOW_POLICY_MODAL: "show-policy-modal",
+ SHOW_DELETE_MODAL: "show-delete-modal",
+ SET_BLOCK_UI: "set-block-ui",
+ SHOW_ALERT: "show-alert",
+ IMPORT_POLICY: "import-policy"
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/reducer.js b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/reducer.js
new file mode 100644
index 0000000..1c5d312
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/PolicyListing/reducer.js
@@ -0,0 +1,130 @@
+/*
+ * 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 moment from "moment-timezone";
+import { ACTIONS } from "./action";
+
+export const INITIAL_STATE = (initialArg) => {
+ return {
+ loader: true,
+ contentLoader: true,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ tableListingData: [],
+ totalCount: 0,
+ pageCount:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage
+ : 0,
+ currentPageIndex:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage - 1
+ : 0,
+ currentPageSize:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.pageSize
+ : 25,
+ resetPage: { page: 0 },
+ tablePageData: {
+ totalPage: 0,
+ pageRecords: 0,
+ pageSize: 25
+ },
+ refreshTableData: moment.now(),
+ showPolicyModal: false,
+ policyData: null,
+ showDeleteModal: false,
+ policyDetail: { policyId: "", policyName: "" },
+ blockUi: false,
+ showAlert: true,
+ showImportPolicyModal: false,
+ importPolicyFile: null,
+ importPolicyStatusMsg: [],
+ importPolicyLoading: false
+ };
+};
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.SET_TABLE_LOADER:
+ return {
+ ...state,
+ loader: action.loader
+ };
+ case ACTIONS.SET_CONTENT_LOADER:
+ return {
+ ...state,
+ contentLoader: action.contentLoader
+ };
+ case ACTIONS.SET_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case ACTIONS.SET_TABLE_DATA:
+ return {
+ ...state,
+ tableListingData: action.tableListingData,
+ totalCount: action.totalCount,
+ pageCount: action.pageCount,
+ currentPageIndex: action.currentPageIndex,
+ currentPageSize: action.currentPageSize,
+ resetPage: action.resetPage,
+ tablePageData: action.tablePageData
+ };
+ case ACTIONS.SHOW_POLICY_MODAL:
+ return {
+ ...state,
+ showPolicyModal: action.showPolicyModal,
+ policyData: action.policyData
+ };
+ case ACTIONS.SHOW_DELETE_MODAL:
+ return {
+ ...state,
+ showDeleteModal: action.showDeleteModal,
+ policyDetail: action.policyDetail
+ };
+ case ACTIONS.SET_BLOCK_UI:
+ return {
+ ...state,
+ blockUi: action.blockUi
+ };
+ case ACTIONS.SHOW_ALERT:
+ return {
+ ...state,
+ showAlert: action.showAlert
+ };
+ case ACTIONS.IMPORT_POLICY:
+ return {
+ ...state,
+ showImportPolicyModal: action.showImportPolicyModal,
+ importPolicyFile: action.importPolicyFile,
+ importPolicyStatusMsg: action.importPolicyStatusMsg,
+ importPolicyLoading: action.importPolicyLoading
+ };
+ default:
+ return state;
+ }
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/GroupAssociateUserDetails.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/GroupAssociateUserDetails.jsx
index aa6db62..dadfed1 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/GroupAssociateUserDetails.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/GroupAssociateUserDetails.jsx
@@ -22,11 +22,11 @@
import { Button, Row, Col, Alert } from "react-bootstrap";
import { isAuditor, isKMSAuditor, serverError } from "Utils/XAUtils";
import { toast } from "react-toastify";
-import { ModalLoader } from "../../components/CommonComponents";
+import { ModalLoader } from "Components/CommonComponents";
import { map } from "lodash";
function GroupAssociateUserDetails(props) {
- const { groupID } = props;
+ const { groupId } = props;
const [userListData, setUserDataList] = useState([]);
const [filterUserListData, setFilterUserDataList] = useState({
searchUser: null,
@@ -48,7 +48,7 @@
let userList;
try {
userList = await fetchApi({
- url: `xusers/${groupID}/users`,
+ url: `xusers/${groupId}/users`,
method: "GET",
params: {
pageSize: totalCount || 100,
@@ -192,7 +192,7 @@
) : (
<>
<center className="text-muted">
- No user associate with this group.!!
+ No users are associated with this group !!
</center>
</>
)}
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/SyncSourceDetails.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/SyncSourceDetails.jsx
index f744ebc..b5ad596 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/SyncSourceDetails.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/SyncSourceDetails.jsx
@@ -19,7 +19,7 @@
import React from "react";
import { Table } from "react-bootstrap";
-import { UsersyncDetailsKeyDisplayMap } from "../../utils/XAEnums";
+import { UsersyncDetailsKeyDisplayMap } from "Utils/XAEnums";
import dateFormat from "dateformat";
export function SyncSourceDetails(props) {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupForm.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupForm.jsx
index ed0e91f..3082873 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupForm.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupForm.jsx
@@ -21,20 +21,20 @@
import { Button, Row, Col } from "react-bootstrap";
import { Form, Field } from "react-final-form";
import { toast } from "react-toastify";
-import { commonBreadcrumb, serverError } from "../../../utils/XAUtils";
+import { commonBreadcrumb, serverError } from "Utils/XAUtils";
import { SyncSourceDetails } from "../SyncSourceDetails";
import {
Loader,
scrollToError,
- CustomTooltip
+ CustomTooltip,
+ BlockUi
} from "Components/CommonComponents";
import { useParams, useLocation, useNavigate } from "react-router-dom";
import usePrompt from "Hooks/usePrompt";
import { fetchApi } from "Utils/fetchAPI";
-import { RegexValidation, GroupSource } from "../../../utils/XAEnums";
-import { BlockUi } from "../../../components/CommonComponents";
+import { RegexValidation, GroupSource } from "Utils/XAEnums";
-const initialState = {
+const INITIAL_STATE = {
groupInfo: {},
groupType: {},
loader: true,
@@ -48,7 +48,7 @@
return null;
};
-const groupFormReducer = (state, action) => {
+const reducer = (state, action) => {
switch (action.type) {
case "SET_LOADER":
return {
@@ -79,11 +79,11 @@
function GroupForm() {
const params = useParams();
- const [groupDetails, dispatch] = useReducer(groupFormReducer, initialState);
- const { groupType, groupInfo, loader, preventUnBlock, blockUI } =
- groupDetails;
- const { state } = useLocation();
const navigate = useNavigate();
+ const { state: navigateState } = useLocation();
+
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
+ const { groupType, groupInfo, loader, preventUnBlock, blockUI } = state;
useEffect(() => {
if (params?.groupID) {
@@ -119,6 +119,7 @@
let formData = {};
formData.name = values.name;
formData.description = values.description || "";
+
let groupFormData = {
...groupInfo,
...formData
@@ -128,6 +129,7 @@
type: "SET_PREVENT_ALERT",
preventUnBlock: true
});
+
if (params?.groupID) {
try {
dispatch({
@@ -164,14 +166,20 @@
method: "post",
data: formData
});
- let tblpageData = {};
- if (state && state != null) {
- tblpageData = state.tblpageData;
- if (state.tblpageData.pageRecords % state.tblpageData.pageSize == 0) {
- tblpageData["totalPage"] = state.tblpageData.totalPage + 1;
+ let tablePageData = {};
+ if (navigateState && navigateState != null) {
+ tablePageData = navigateState.tablePageData;
+ if (
+ navigateState.tablePageData.pageRecords %
+ navigateState.tablePageData.pageSize ==
+ 0
+ ) {
+ tablePageData["totalPage"] =
+ navigateState.tablePageData.totalPage + 1;
} else {
- if (tblpageData !== undefined) {
- tblpageData["totalPage"] = state.tblpageData.totalPage;
+ if (tablePageData !== undefined) {
+ tablePageData["totalPage"] =
+ navigateState.tablePageData.totalPage;
}
}
}
@@ -183,7 +191,7 @@
navigate("/users/grouptab", {
state: {
showLastPage: true,
- addPageData: tblpageData
+ addPageData: tablePageData
}
});
} catch (error) {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupListing.jsx
index b6a9bcd..aa80ebc 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupListing.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/GroupListing.jsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
+import React, { useCallback, useRef, useEffect, useReducer } from "react";
import {
Badge,
Button,
@@ -28,8 +28,8 @@
Dropdown
} from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
-import { GroupSource } from "../../../utils/XAEnums";
-import { GroupTypes } from "../../../utils/XAEnums";
+import { GroupSource } from "Utils/XAEnums";
+import { GroupTypes } from "Utils/XAEnums";
import { VisibilityStatus } from "Utils/XAEnums";
import {
useNavigate,
@@ -50,52 +50,24 @@
serverError,
parseSearchFilter
} from "Utils/XAUtils";
-import { find, isUndefined, isEmpty } from "lodash";
-import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
-import {
- BlockUi,
- Loader,
- scrollToNewData
-} from "../../../components/CommonComponents";
+import { find, isUndefined, isEmpty, pick } from "lodash";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
+import { BlockUi, Loader, scrollToNewData } from "Components/CommonComponents";
+import { ACTIONS } from "./action";
+import { reducer, INITIAL_STATE } from "./reducer";
-function Groups() {
+function GroupListing() {
const navigate = useNavigate();
- const { state } = useLocation();
- const [groupListingData, setGroupData] = useState([]);
- const [loader, setLoader] = useState(true);
- const [totalCount, setTotalCount] = useState(0);
- const fetchIdRef = useRef(0);
+ const { state: navigateState, search } = useLocation();
+
+ let initialArg = { navigateState: navigateState };
+
+ const [state, dispatch] = useReducer(reducer, initialArg, INITIAL_STATE);
+
+ const [searchParams, setSearchParams] = useSearchParams();
+
const selectedRows = useRef([]);
const toastId = useRef(null);
- const [showModal, setConfirmModal] = useState(false);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [showGroupSyncDetails, setGroupSyncdetails] = useState({
- syncDteails: {},
- showSyncDetails: false
- });
- const [showAssociateUserModal, setAssociateUserModal] = useState(false);
- const [pageCount, setPageCount] = useState(
- state && state.showLastPage ? state.addPageData.totalPage : 0
- );
- const [currentpageIndex, setCurrentPageIndex] = useState(
- state && state.showLastPage ? state.addPageData.totalPage - 1 : 0
- );
- const [currentpageSize, setCurrentPageSize] = useState(
- state && state.showLastPage ? state.addPageData.pageSize : 25
- );
- const [resetPage, setResetPage] = useState({ page: 0 });
- const [tblpageData, setTblPageData] = useState({
- totalPage: 0,
- pageRecords: 0,
- pageSize: 25
- });
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [pageLoader, setPageLoader] = useState(true);
- const [blockUI, setBlockUI] = useState(false);
useEffect(() => {
let searchFilterParam = {};
@@ -131,96 +103,115 @@
// Updating the states for search params, search filter and default search filter
setSearchParams({ ...currentParams, ...searchParam }, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- setPageLoader(false);
- localStorage.setItem("newDataAdded", state && state.showLastPage);
- }, [searchParams]);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ localStorage.setItem(
+ "newDataAdded",
+ navigateState && navigateState.showLastPage
+ );
+ }, [search]);
+
useEffect(() => {
if (localStorage.getItem("newDataAdded") == "true") {
- scrollToNewData(groupListingData);
+ scrollToNewData(state.tableListingData);
}
- }, [totalCount]);
- const fetchGroupInfo = useCallback(
+ }, [state.totalCount]);
+
+ const fetchGroups = useCallback(
async ({ pageSize, pageIndex, gotoPage }) => {
- setLoader(true);
- let groupData = [],
- groupResp = [];
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+ let groupData = [];
let totalCount = 0;
let page =
- state && state.showLastPage
- ? state.addPageData.totalPage - 1
+ navigateState && navigateState.showLastPage
+ ? navigateState.addPageData.totalPage - 1
: pageIndex;
let totalPageCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["page"] = page;
- params["startIndex"] =
- state && state.showLastPage
- ? (state.addPageData.totalPage - 1) * pageSize
- : pageIndex * pageSize;
- params["pageSize"] = pageSize;
- try {
- groupResp = await fetchApi({
- url: "xusers/groups",
- params: params
- });
- groupData = groupResp.data.vXGroups;
- totalCount = groupResp.data.totalCount;
- totalPageCount = Math.ceil(totalCount / pageSize);
- } catch (error) {
- serverError(error);
- console.error(`Error occurred while fetching User list! ${error}`);
- }
- if (state) {
- state["showLastPage"] = false;
- }
- setGroupData(groupData);
- setTblPageData({
- totalPage: totalPageCount,
- pageRecords: groupResp && groupResp.data && groupResp.data.totalCount,
- pageSize: pageSize
+ let params = { ...state.searchFilterParams };
+
+ params["page"] = page;
+ params["startIndex"] =
+ navigateState && navigateState.showLastPage
+ ? (navigateState.addPageData.totalPage - 1) * pageSize
+ : pageIndex * pageSize;
+ params["pageSize"] = pageSize;
+
+ try {
+ const response = await fetchApi({
+ url: "xusers/groups",
+ params: params
});
- setTotalCount(totalCount);
- setPageCount(totalPageCount);
- setCurrentPageIndex(page);
- setCurrentPageSize(pageSize);
- setResetPage({ page: gotoPage });
- setLoader(false);
+ groupData = response.data?.vXGroups || [];
+ totalCount = response.data?.totalCount || 0;
+ totalPageCount = Math.ceil(totalCount / pageSize);
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching groups ! ${error}`);
}
+
+ if (navigateState) {
+ navigateState["showLastPage"] = false;
+ }
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: groupData,
+ totalCount: totalCount,
+ pageCount: totalPageCount,
+ currentPageIndex: page,
+ currentPageSize: pageSize,
+ resetPage: { page: gotoPage },
+ tablePageData: {
+ totalPage: totalPageCount,
+ pageRecords: totalCount,
+ pageSize: pageSize
+ }
+ });
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
- const handleDeleteBtnClick = () => {
+ const groupDelete = () => {
if (selectedRows.current.length > 0) {
- toggleConfirmModal();
+ toggleGroupDeleteModal();
} else {
toast.dismiss(toastId.current);
- toastId.current = toast.warning("Please select atleast one group!!");
+ toastId.current = toast.warning("Please select atleast one group !!");
}
};
- const toggleConfirmModal = () => {
- setConfirmModal((state) => !state);
+ const toggleGroupDeleteModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_DELETE_MODAL,
+ showDeleteModal: !state.showDeleteModal
+ });
};
- const handleConfirmClick = () => {
- handleDeleteClick();
+ const confirmGroupDelete = () => {
+ handleGroupDelete();
};
- const handleDeleteClick = async () => {
+ const handleGroupDelete = async () => {
const selectedData = selectedRows.current;
let errorMsg = "";
if (selectedData.length > 0) {
- toggleConfirmModal();
+ toggleGroupDeleteModal();
for (const { original } of selectedData) {
try {
- setBlockUI(true);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: true });
await fetchApi({
url: `xusers/secure/groups/id/${original.id}`,
method: "DELETE",
@@ -228,14 +219,14 @@
forceDelete: true
}
});
- setBlockUI(false);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
} catch (error) {
- setBlockUI(false);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
if (error?.response?.data?.msgDesc) {
errorMsg += error.response.data.msgDesc + "\n";
} else {
errorMsg +=
- `Error occurred during deleting Groups: ${original.name}` + "\n";
+ `Error occurred during deleting group: ${original.name}` + "\n";
}
console.error(errorMsg);
}
@@ -245,17 +236,21 @@
toastId.current = toast.error(errorMsg);
} else {
toast.dismiss(toastId.current);
- toastId.current = toast.success("Group deleted successfully!");
+ toastId.current = toast.success("Group deleted successfully !");
if (
- (groupListingData.length == 1 ||
- groupListingData.length == selectedRows.current.length) &&
- currentpageIndex > 0
+ (state.tableListingData.length == 1 ||
+ state.tableListingData.length == selectedRows.current.length) &&
+ state.currentPageIndex > 0
) {
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
} else {
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
}
}
}
@@ -275,10 +270,10 @@
toastId.current = toast.warning(
e == VisibilityStatus.STATUS_VISIBLE.value
? `Selected ${
- selectedRows.current.length === 1 ? "Group is" : "Groups are"
+ selectedRows.current.length === 1 ? "group is" : "groups are"
} already visible`
: `Selected ${
- selectedRows.current.length === 1 ? "Group is " : "Groups are"
+ selectedRows.current.length === 1 ? "group is " : "groups are"
} already hidden`
);
return;
@@ -292,20 +287,64 @@
toast.dismiss(toastId.current);
toastId.current = toast.success(
`Sucessfully updated ${
- selectedRows.current.length === 1 ? "Group" : "Groups"
- } visibility!!`
+ selectedRows.current.length === 1 ? "group" : "groups"
+ } visibility !!`
);
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
} catch (error) {
serverError(error);
- console.error(`Error occurred during set Group visibility! ${error}`);
+ console.error(`Error occurred during set group visibility ! ${error}`);
}
} else {
toast.dismiss(toastId.current);
- toastId.current = toast.warning("Please select atleast one group!!");
+ toastId.current = toast.warning("Please select atleast one group !!");
}
};
+ const addGroup = () => {
+ navigate("/group/create", {
+ state: { tablePageData: state.tablePageData }
+ });
+ };
+
+ const openSyncDetailsModal = (value) => {
+ dispatch({
+ type: ACTIONS.SHOW_SYNC_DETAILS_MODAL,
+ showSyncDetailsModal: true,
+ syncDetailsData: JSON.parse(value)
+ });
+ };
+
+ const hideSyncDetailsModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_SYNC_DETAILS_MODAL,
+ showSyncDetailsModal: false,
+ syncDetailsData: {}
+ });
+ };
+
+ const openGroupUsersModal = (group) => {
+ let groupParams = pick(group, ["id", "name"]);
+
+ dispatch({
+ type: ACTIONS.SHOW_GROUP_USERS_MODAL,
+ showGroupUsersModal: true,
+ groupData: groupParams
+ });
+ };
+
+ const hideGroupUsersModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_GROUP_USERS_MODAL,
+ showGroupUsersModal: false,
+ groupData: { id: "", name: "" }
+ });
+ };
+
const columns = React.useMemo(
() => [
{
@@ -416,7 +455,7 @@
title="View Users"
data-js="showUserList"
onClick={() => {
- showGroupAssociateUser(rawValue.row.original);
+ openGroupUsersModal(rawValue.row.original);
}}
data-cy="showUserList"
>
@@ -430,7 +469,7 @@
{
Header: "Sync Details",
accessor: "otherAttributes",
- Cell: (rawValue, model) => {
+ Cell: (rawValue) => {
if (rawValue.value) {
return (
<div className="text-center">
@@ -440,9 +479,8 @@
data-cy="syncDetailes"
data-for="group"
title="Sync Details"
- id={model.id}
onClick={() => {
- toggleGroupSyncModal(rawValue.value);
+ openSyncDetailsModal(rawValue.value);
}}
>
<i className="fa-fw fa fa-eye"> </i>
@@ -458,34 +496,6 @@
],
[]
);
- const addGroup = () => {
- navigate("/group/create", { state: { tblpageData: tblpageData } });
- };
- const toggleGroupSyncModal = (raw) => {
- setGroupSyncdetails({
- syncDteails: JSON.parse(raw),
- showSyncDetails: true
- });
- };
- const toggleGroupSyncModalClose = () => {
- setGroupSyncdetails({
- syncDteails: {},
- showSyncDetails: false
- });
- };
- const showGroupAssociateUser = (raw) => {
- setAssociateUserModal({
- groupID: raw.id,
- groupName: raw.name,
- showAssociateUserDetails: true
- });
- };
- const toggleAssociateUserClose = () => {
- setAssociateUserModal({
- groupID: "",
- showAssociateUserDetails: false
- });
- };
const searchFilterOptions = [
{
@@ -534,26 +544,31 @@
];
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
return (
<div className="wrap">
- {pageLoader ? (
+ {state.contentLoader ? (
<Loader />
) : (
<React.Fragment>
- <BlockUi isUiBlock={blockUI} />
+ <BlockUi isUiBlock={state.blockUi} />
<Row className="mb-4">
<Col md={8} className="usr-grp-role-search-width">
<StructuredFilter
@@ -561,7 +576,7 @@
placeholder="Search for your groups..."
options={searchFilterOptions}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</Col>
{isSystemAdmin() && (
@@ -591,7 +606,7 @@
size="sm"
title="Delete"
className="ms-2"
- onClick={handleDeleteBtnClick}
+ onClick={groupDelete}
data-id="deleteUserGroup"
data-cy="deleteUserGroup"
>
@@ -602,14 +617,14 @@
</Row>
<XATableLayout
- data={groupListingData}
+ data={state.tableListingData}
columns={columns}
- fetchData={fetchGroupInfo}
- totalCount={totalCount}
- pageCount={pageCount}
- currentpageIndex={currentpageIndex}
- currentpageSize={currentpageSize}
- loading={loader}
+ fetchData={fetchGroups}
+ totalCount={state.totalCount}
+ pageCount={state.pageCount}
+ currentpageIndex={state.currentPageIndex}
+ currentpageSize={state.currentPageSize}
+ loading={state.loader}
pagination
rowSelectOp={
(isSystemAdmin() || isKeyAdmin()) && {
@@ -622,7 +637,7 @@
})}
/>
- <Modal show={showModal} onHide={toggleConfirmModal}>
+ <Modal show={state.showDeleteModal} onHide={toggleGroupDeleteModal}>
<Modal.Header closeButton>
<span className="text-word-break">
Are you sure you want to delete the
@@ -642,44 +657,43 @@
<Button
variant="secondary"
size="sm"
- onClick={toggleConfirmModal}
+ onClick={toggleGroupDeleteModal}
>
Close
</Button>
- <Button variant="primary" size="sm" onClick={handleConfirmClick}>
+ <Button variant="primary" size="sm" onClick={confirmGroupDelete}>
OK
</Button>
</Modal.Footer>
</Modal>
+
<Modal
- show={showGroupSyncDetails && showGroupSyncDetails.showSyncDetails}
- onHide={toggleGroupSyncModalClose}
+ show={state.showSyncDetailsModal}
+ onHide={hideSyncDetailsModal}
size="xl"
>
- <Modal.Header>
+ <Modal.Header closeButton>
<Modal.Title>Sync Source Details</Modal.Title>
</Modal.Header>
<Modal.Body>
<SyncSourceDetails
- syncDetails={showGroupSyncDetails.syncDteails}
+ syncDetails={state.syncDetailsData}
></SyncSourceDetails>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
size="sm"
- onClick={toggleGroupSyncModalClose}
+ onClick={hideSyncDetailsModal}
>
OK
</Button>
</Modal.Footer>
</Modal>
+
<Modal
- show={
- showAssociateUserModal &&
- showAssociateUserModal.showAssociateUserDetails
- }
- onHide={toggleAssociateUserClose}
+ show={state.showGroupUsersModal}
+ onHide={hideGroupUsersModal}
size="lg"
>
<Modal.Header closeButton>
@@ -688,24 +702,20 @@
User's List :
<div
className="ps-2 more-less-width text-truncate"
- title={showAssociateUserModal?.groupName}
+ title={state.groupData.name}
>
- {showAssociateUserModal.groupName}
+ {state.groupData.name}
</div>
</div>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<GroupAssociateUserDetails
- groupID={showAssociateUserModal.groupID}
+ groupId={state.groupData.id}
></GroupAssociateUserDetails>
</Modal.Body>
<Modal.Footer>
- <Button
- variant="primary"
- size="sm"
- onClick={toggleAssociateUserClose}
- >
+ <Button variant="primary" size="sm" onClick={hideGroupUsersModal}>
OK
</Button>
</Modal.Footer>
@@ -716,4 +726,4 @@
);
}
-export default Groups;
+export default GroupListing;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/action.js b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/action.js
new file mode 100644
index 0000000..73cfacb
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/action.js
@@ -0,0 +1,30 @@
+/*
+ * 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.
+ */
+
+export const ACTIONS = {
+ SET_TABLE_LOADER: "set-table-loader",
+ SET_CONTENT_LOADER: "set-content-loader",
+ SET_SEARCH_FILTER_PARAMS: "set-search-filter-params",
+ SET_DEFAULT_SEARCH_FILTER_PARAMS: "set-default-search-filter-params",
+ SET_TABLE_DATA: "set-table-data",
+ SHOW_DELETE_MODAL: "show-delete-modal",
+ SHOW_SYNC_DETAILS_MODAL: "show-sync-details-modal",
+ SHOW_GROUP_USERS_MODAL: "show-group-users-modal",
+ SET_BLOCK_UI: "set-block-ui"
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/reducer.js b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/reducer.js
new file mode 100644
index 0000000..76ca47a
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/groups_details/reducer.js
@@ -0,0 +1,118 @@
+/*
+ * 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 moment from "moment-timezone";
+import { ACTIONS } from "./action";
+
+export const INITIAL_STATE = (initialArg) => {
+ return {
+ loader: true,
+ contentLoader: true,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ tableListingData: [],
+ totalCount: 0,
+ pageCount:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage
+ : 0,
+ currentPageIndex:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage - 1
+ : 0,
+ currentPageSize:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.pageSize
+ : 25,
+ resetPage: { page: 0 },
+ tablePageData: {
+ totalPage: 0,
+ pageRecords: 0,
+ pageSize: 25
+ },
+ refreshTableData: moment.now(),
+ showDeleteModal: false,
+ showSyncDetailsModal: false,
+ syncDetailsData: {},
+ showGroupUsersModal: false,
+ groupData: { id: "", name: "" },
+ blockUi: false
+ };
+};
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.SET_TABLE_LOADER:
+ return {
+ ...state,
+ loader: action.loader
+ };
+ case ACTIONS.SET_CONTENT_LOADER:
+ return {
+ ...state,
+ contentLoader: action.contentLoader
+ };
+ case ACTIONS.SET_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case ACTIONS.SET_TABLE_DATA:
+ return {
+ ...state,
+ tableListingData: action.tableListingData,
+ totalCount: action.totalCount,
+ pageCount: action.pageCount,
+ currentPageIndex: action.currentPageIndex,
+ currentPageSize: action.currentPageSize,
+ resetPage: action.resetPage,
+ tablePageData: action.tablePageData
+ };
+ case ACTIONS.SHOW_DELETE_MODAL:
+ return {
+ ...state,
+ showDeleteModal: action.showDeleteModal
+ };
+ case ACTIONS.SHOW_SYNC_DETAILS_MODAL:
+ return {
+ ...state,
+ showSyncDetailsModal: action.showSyncDetailsModal,
+ syncDetailsData: action.syncDetailsData
+ };
+ case ACTIONS.SHOW_GROUP_USERS_MODAL:
+ return {
+ ...state,
+ showGroupUsersModal: action.showGroupUsersModal,
+ groupData: action.groupData
+ };
+ case ACTIONS.SET_BLOCK_UI:
+ return {
+ ...state,
+ blockUi: action.blockUi
+ };
+ default:
+ return state;
+ }
+};
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 a58fb9c..222d901 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
@@ -38,7 +38,7 @@
import usePrompt from "Hooks/usePrompt";
import { RegexValidation } from "Utils/XAEnums";
-const initialState = {
+const INITIAL_STATE = {
loader: true,
roleInfo: {},
selectedUser: [],
@@ -99,9 +99,10 @@
function RoleForm() {
const params = useParams();
- const { state } = useLocation();
const navigate = useNavigate();
- const [roleFormState, dispatch] = useReducer(reducer, initialState);
+ const { state: navigateState } = useLocation();
+
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
const {
loader,
roleInfo,
@@ -110,8 +111,10 @@
selectedGroup,
preventUnBlock,
blockUI
- } = roleFormState;
+ } = state;
+
const toastId = React.useRef(null);
+
useEffect(() => {
if (params?.roleID) {
fetchRoleData(params.roleID);
@@ -133,6 +136,7 @@
return findIndex(selectedUser, data) === -1;
}
};
+
const filterGroupOp = (data, formVal) => {
if (formVal && formVal.groups) {
let groupSelectedData = formVal.groups.map((m) => {
@@ -143,6 +147,7 @@
return findIndex(selectedGroup, data) === -1;
}
};
+
const filterRoleOp = (data, formVal) => {
if (formVal && formVal.roles) {
let roleSelectedData = formVal.roles.map((m) => {
@@ -231,14 +236,20 @@
method: "post",
data: formData
});
- let tblpageData = {};
- if (state && state != null) {
- tblpageData = state.tblpageData;
- if (state.tblpageData.pageRecords % state.tblpageData.pageSize == 0) {
- tblpageData["totalPage"] = state.tblpageData.totalPage + 1;
+ let tablePageData = {};
+ if (navigateState && navigateState != null) {
+ tablePageData = navigateState.tablePageData;
+ if (
+ navigateState.tablePageData.pageRecords %
+ navigateState.tablePageData.pageSize ==
+ 0
+ ) {
+ tablePageData["totalPage"] =
+ navigateState.tablePageData.totalPage + 1;
} else {
- if (tblpageData !== undefined) {
- tblpageData["totalPage"] = state.tblpageData.totalPage;
+ if (tablePageData !== undefined) {
+ tablePageData["totalPage"] =
+ navigateState.tablePageData.totalPage;
}
}
}
@@ -250,7 +261,7 @@
navigate("/users/roletab", {
state: {
showLastPage: true,
- addPageData: tblpageData
+ addPageData: tablePageData
}
});
} catch (error) {
@@ -412,6 +423,7 @@
}
return formValueObj;
};
+
const validateForm = (values) => {
const errors = {};
if (!values.name) {
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleListing.jsx
index df28b25..c300009 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleListing.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/RoleListing.jsx
@@ -17,10 +17,15 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
+import React, { useCallback, useRef, useEffect, useReducer } from "react";
import { Button, Row, Col, Modal } from "react-bootstrap";
import XATableLayout from "Components/XATableLayout";
-import { MoreLess, scrollToNewData } from "Components/CommonComponents";
+import {
+ BlockUi,
+ Loader,
+ MoreLess,
+ scrollToNewData
+} from "Components/CommonComponents";
import {
useNavigate,
Link,
@@ -28,7 +33,7 @@
useSearchParams
} from "react-router-dom";
import moment from "moment-timezone";
-import { find, isEmpty, map } from "lodash";
+import { find, isEmpty, isUndefined, map } from "lodash";
import { fetchApi } from "Utils/fetchAPI";
import { toast } from "react-toastify";
import {
@@ -39,44 +44,21 @@
serverError,
parseSearchFilter
} from "Utils/XAUtils";
-import { isUndefined } from "lodash";
-import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
-import { Loader } from "../../../components/CommonComponents";
-import { BlockUi } from "../../../components/CommonComponents";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
+import { ACTIONS } from "./action";
+import { reducer, INITIAL_STATE } from "./reducer";
-function Roles() {
+function RoleListing() {
const navigate = useNavigate();
- const { state } = useLocation();
- const [roleListingData, setRoleData] = useState([]);
- const [loader, setLoader] = useState(true);
- const [pageLoader, setPageLoader] = useState(true);
+ const { state: navigateState, search } = useLocation();
- const [totalCount, setTotalCount] = useState(0);
- const fetchIdRef = useRef(0);
- const selectedRows = useRef([]);
- const [showModal, setConfirmModal] = useState(false);
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [pageCount, setPageCount] = useState(
- state && state.showLastPage ? state.addPageData.totalPage : 0
- );
- const [currentpageIndex, setCurrentPageIndex] = useState(
- state && state.showLastPage ? state.addPageData.totalPage - 1 : 0
- );
- const [currentpageSize, setCurrentPageSize] = useState(
- state && state.showLastPage ? state.addPageData.pageSize : 25
- );
- const [resetPage, setResetPage] = useState({ page: 0 });
- const [tblpageData, setTblPageData] = useState({
- totalPage: 0,
- pageRecords: 0,
- pageSize: 25
- });
- const [searchFilterParams, setSearchFilterParams] = useState([]);
+ let initialArg = { navigateState: navigateState };
+
+ const [state, dispatch] = useReducer(reducer, initialArg, INITIAL_STATE);
+
const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const [blockUI, setBlockUI] = useState(false);
+
+ const selectedRows = useRef([]);
useEffect(() => {
let searchFilterParam = {};
@@ -112,109 +94,126 @@
// Updating the states for search params, search filter and default search filter
setSearchParams({ ...currentParams, ...searchParam }, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- setPageLoader(false);
- localStorage.setItem("newDataAdded", state && state.showLastPage);
- }, [searchParams]);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ localStorage.setItem(
+ "newDataAdded",
+ navigateState && navigateState.showLastPage
+ );
+ }, [search]);
useEffect(() => {
if (localStorage.getItem("newDataAdded") == "true") {
- scrollToNewData(roleListingData);
+ scrollToNewData(state.tableListingData);
}
- }, [totalCount]);
+ }, [state.totalCount]);
- const fetchRoleInfo = useCallback(
+ const fetchRoles = useCallback(
async ({ pageSize, pageIndex, gotoPage }) => {
- setLoader(true);
- let roleData = [],
- roleResp = [];
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+ let roleData = [];
let totalCount = 0;
let page =
- state && state.showLastPage
- ? state.addPageData.totalPage - 1
+ navigateState && navigateState.showLastPage
+ ? navigateState.addPageData.totalPage - 1
: pageIndex;
let totalPageCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
- if (fetchId === fetchIdRef.current) {
- params["page"] = page;
- params["startIndex"] =
- state && state.showLastPage
- ? (state.addPageData.totalPage - 1) * pageSize
- : pageIndex * pageSize;
- params["pageSize"] = pageSize;
- try {
- roleResp = await fetchApi({
- url: "roles/lookup/roles",
- params: params
- });
- roleData = roleResp.data.roles;
- totalCount = roleResp.data.totalCount;
- totalPageCount = Math.ceil(totalCount / pageSize);
- } catch (error) {
- serverError(error);
- console.error(`Error occurred while fetching User list! ${error}`);
- }
- if (state) {
- state["showLastPage"] = false;
- }
- setTblPageData({
- totalPage: totalPageCount,
- pageRecords: roleResp && roleResp.data && roleResp.data.totalCount,
- pageSize: 25
+ let params = { ...state.searchFilterParams };
+
+ params["page"] = page;
+ params["startIndex"] =
+ navigateState && navigateState.showLastPage
+ ? (navigateState.addPageData.totalPage - 1) * pageSize
+ : pageIndex * pageSize;
+ params["pageSize"] = pageSize;
+
+ try {
+ const response = await fetchApi({
+ url: "roles/lookup/roles",
+ params: params
});
- setRoleData(roleData);
- setTotalCount(totalCount);
- setPageCount(totalPageCount);
- setCurrentPageIndex(page);
- setCurrentPageSize(pageSize);
- setResetPage({ page: gotoPage });
- setLoader(false);
+ roleData = response.data.roles || [];
+ totalCount = response.data.totalCount || 0;
+ totalPageCount = Math.ceil(totalCount / pageSize);
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching roles ! ${error}`);
}
+
+ if (navigateState) {
+ navigateState["showLastPage"] = false;
+ }
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: roleData,
+ totalCount: totalCount,
+ pageCount: totalPageCount,
+ currentPageIndex: page,
+ currentPageSize: pageSize,
+ resetPage: { page: gotoPage },
+ tablePageData: {
+ totalPage: totalPageCount,
+ pageRecords: totalCount,
+ pageSize: pageSize
+ }
+ });
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
- const handleDeleteBtnClick = () => {
+ const roleDelete = () => {
if (selectedRows.current.length > 0) {
- toggleConfirmModal();
+ toggleRoleDeleteModal();
} else {
- toast.warning("Please select atleast one role!!");
+ toast.warning("Please select atleast one role !!");
}
};
- const toggleConfirmModal = () => {
- setConfirmModal((state) => !state);
+ const toggleRoleDeleteModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_DELETE_MODAL,
+ showDeleteModal: !state.showDeleteModal
+ });
};
- const handleConfirmClick = () => {
- handleDeleteClick();
+ const confirmRoleDelete = () => {
+ handleRoleDelete();
};
- const handleDeleteClick = async () => {
+ const handleRoleDelete = async () => {
const selectedData = selectedRows.current;
let errorMsg = "";
if (selectedData.length > 0) {
- toggleConfirmModal();
+ toggleRoleDeleteModal();
for (const { original } of selectedData) {
try {
- setBlockUI(true);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: true });
await fetchApi({
url: `roles/roles/${original.id}`,
method: "DELETE"
});
- setBlockUI(false);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
} catch (error) {
- setBlockUI(false);
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
if (error?.response?.data?.msgDesc) {
errorMsg += error.response.data.msgDesc + "\n";
} else {
errorMsg +=
- `Error occurred during deleting Role: ${original.name}` + "\n";
+ `Error occurred during deleting role: ${original.name}` + "\n";
}
console.error(errorMsg);
}
@@ -222,22 +221,32 @@
if (errorMsg) {
toast.error(errorMsg);
} else {
- toast.success("Role deleted successfully!");
+ toast.success("Role deleted successfully !");
if (
- (roleListingData.length == 1 ||
- roleListingData.length == selectedRows.current.length) &&
- currentpageIndex > 0
+ (state.tableListingData.length == 1 ||
+ state.tableListingData.length == selectedRows.current.length) &&
+ state.currentPageIndex > 0
) {
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
} else {
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
}
}
}
};
+ const addRole = () => {
+ navigate("/roles/create", {
+ state: { tablePageData: state.tablePageData }
+ });
+ };
+
const columns = React.useMemo(
() => [
{
@@ -265,7 +274,6 @@
},
{
Header: "Users",
- accessor: "users",
accessor: (raw) => {
let usersList = map(raw.users, "name");
return !isEmpty(usersList) ? (
@@ -277,7 +285,6 @@
},
{
Header: "Groups",
- accessor: "groups",
accessor: (raw) => {
let groupsList = map(raw.groups, "name");
return !isEmpty(groupsList) ? (
@@ -289,7 +296,6 @@
},
{
Header: "Roles",
- accessor: "roles",
accessor: (raw) => {
let rolesList = map(raw.roles, "name");
@@ -304,10 +310,6 @@
[]
);
- const addRole = () => {
- navigate("/roles/create", { state: { tblpageData: tblpageData } });
- };
-
const searchFilterOptions = [
{
category: "groupNamePartial",
@@ -330,25 +332,31 @@
];
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
return (
<div className="wrap">
- {pageLoader ? (
+ {state.contentLoader ? (
<Loader />
) : (
<React.Fragment>
- <BlockUi isUiBlock={blockUI} />
+ <BlockUi isUiBlock={state.blockUi} />
<Row className="mb-4">
<Col md={8} className="usr-grp-role-search-width">
<StructuredFilter
@@ -356,7 +364,7 @@
placeholder="Search for your roles..."
options={searchFilterOptions}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</Col>
{isSystemAdmin() && (
@@ -375,7 +383,7 @@
variant="danger"
size="sm"
title="Delete"
- onClick={handleDeleteBtnClick}
+ onClick={roleDelete}
data-id="deleteUserGroup"
data-cy="deleteUserGroup"
>
@@ -386,15 +394,15 @@
</Row>
<XATableLayout
- data={roleListingData}
+ data={state.tableListingData}
columns={columns}
- fetchData={fetchRoleInfo}
- totalCount={totalCount}
- pageCount={pageCount}
- currentpageIndex={currentpageIndex}
- currentpageSize={currentpageSize}
+ fetchData={fetchRoles}
+ totalCount={state.totalCount}
+ pageCount={state.pageCount}
+ currentpageIndex={state.currentPageIndex}
+ currentpageSize={state.currentPageSize}
pagination
- loading={loader}
+ loading={state.loader}
rowSelectOp={
(isSystemAdmin() || isKeyAdmin()) && {
position: "first",
@@ -403,7 +411,7 @@
}
/>
- <Modal show={showModal} onHide={toggleConfirmModal}>
+ <Modal show={state.showDeleteModal} onHide={toggleRoleDeleteModal}>
<Modal.Header closeButton>
<span className="text-word-break">
Are you sure you want to delete the
@@ -423,11 +431,11 @@
<Button
variant="secondary"
size="sm"
- onClick={toggleConfirmModal}
+ onClick={toggleRoleDeleteModal}
>
Close
</Button>
- <Button variant="primary" size="sm" onClick={handleConfirmClick}>
+ <Button variant="primary" size="sm" onClick={confirmRoleDelete}>
OK
</Button>
</Modal.Footer>
@@ -438,4 +446,4 @@
);
}
-export default Roles;
+export default RoleListing;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/action.js b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/action.js
new file mode 100644
index 0000000..c1aa59a
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/action.js
@@ -0,0 +1,28 @@
+/*
+ * 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.
+ */
+
+export const ACTIONS = {
+ SET_TABLE_LOADER: "set-table-loader",
+ SET_CONTENT_LOADER: "set-content-loader",
+ SET_SEARCH_FILTER_PARAMS: "set-search-filter-params",
+ SET_DEFAULT_SEARCH_FILTER_PARAMS: "set-default-search-filter-params",
+ SET_TABLE_DATA: "set-table-data",
+ SHOW_DELETE_MODAL: "show-delete-modal",
+ SET_BLOCK_UI: "set-block-ui"
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/reducer.js b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/reducer.js
new file mode 100644
index 0000000..4f49502
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/role_details/reducer.js
@@ -0,0 +1,102 @@
+/*
+ * 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 moment from "moment-timezone";
+import { ACTIONS } from "./action";
+
+export const INITIAL_STATE = (initialArg) => {
+ return {
+ loader: true,
+ contentLoader: true,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ tableListingData: [],
+ totalCount: 0,
+ pageCount:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage
+ : 0,
+ currentPageIndex:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage - 1
+ : 0,
+ currentPageSize:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.pageSize
+ : 25,
+ resetPage: { page: 0 },
+ tablePageData: {
+ totalPage: 0,
+ pageRecords: 0,
+ pageSize: 25
+ },
+ refreshTableData: moment.now(),
+ showDeleteModal: false,
+ blockUi: false
+ };
+};
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.SET_TABLE_LOADER:
+ return {
+ ...state,
+ loader: action.loader
+ };
+ case ACTIONS.SET_CONTENT_LOADER:
+ return {
+ ...state,
+ contentLoader: action.contentLoader
+ };
+ case ACTIONS.SET_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case ACTIONS.SET_TABLE_DATA:
+ return {
+ ...state,
+ tableListingData: action.tableListingData,
+ totalCount: action.totalCount,
+ pageCount: action.pageCount,
+ currentPageIndex: action.currentPageIndex,
+ currentPageSize: action.currentPageSize,
+ resetPage: action.resetPage,
+ tablePageData: action.tablePageData
+ };
+ case ACTIONS.SHOW_DELETE_MODAL:
+ return {
+ ...state,
+ showDeleteModal: action.showDeleteModal
+ };
+ case ACTIONS.SET_BLOCK_UI:
+ return {
+ ...state,
+ blockUi: action.blockUi
+ };
+ default:
+ return state;
+ }
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/AddUserView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/AddUserView.jsx
index 2a3df84..b917075 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/AddUserView.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/AddUserView.jsx
@@ -18,19 +18,18 @@
*/
import React, { Component } from "react";
-import UserFormComp from "Views/UserGroupRoleListing/users_details/UserFormComp";
-import { commonBreadcrumb } from "../../../utils/XAUtils";
+import UserForm from "Views/UserGroupRoleListing/users_details/UserForm";
+import { commonBreadcrumb } from "Utils/XAUtils";
class AddUserView extends Component {
render() {
return (
<>
- {/* {commonBreadcrumb(["Users", "UserCreate"])} */}
<div className="header-wraper">
<h3 className="wrap-header bold">User Detail</h3>
{commonBreadcrumb(["Users", "UserCreate"])}
</div>
- <UserFormComp />
+ <UserForm />
</>
);
}
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/EditUserView.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/EditUserView.jsx
index 7d04c71..a33396c 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/EditUserView.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/EditUserView.jsx
@@ -20,20 +20,21 @@
import React, { useEffect, useReducer } from "react";
import { Tab, Button, Nav, Row, Col } from "react-bootstrap";
import { Form, Field } from "react-final-form";
-import UserFormComp from "Views/UserGroupRoleListing/users_details/UserFormComp";
+import UserForm from "Views/UserGroupRoleListing/users_details/UserForm";
import { Loader, scrollToError } from "Components/CommonComponents";
import { fetchApi } from "Utils/fetchAPI";
import { UserTypes, RegexValidation } from "Utils/XAEnums";
import { toast } from "react-toastify";
import { useParams, useNavigate } from "react-router-dom";
import { has } from "lodash";
-import { commonBreadcrumb, InfoIcon } from "../../../utils/XAUtils";
+import { commonBreadcrumb, InfoIcon } from "Utils/XAUtils";
-const initialState = {
+const INITIAL_STATE = {
userInfo: {},
loader: true
};
-const userFormReducer = (state, action) => {
+
+const reducer = (state, action) => {
switch (action.type) {
case "SET_LOADER":
return {
@@ -51,12 +52,13 @@
}
};
-function AddUserView() {
+function EditUserView() {
const params = useParams();
- const [userDetails, dispatch] = useReducer(userFormReducer, initialState);
- const { userInfo, loader } = userDetails;
const navigate = useNavigate();
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
+ const { userInfo, loader } = state;
+
useEffect(() => {
if (params?.userID) {
fetchUserData(params.userID);
@@ -140,11 +142,7 @@
<h3 className="wrap-header bold">User Detail</h3>
{commonBreadcrumb(["Users", "UserEdit"], params.userID)}
</div>
- <UserFormComp
- isEditView={true}
- userID={params.userID}
- userInfo={userInfo}
- />
+ <UserForm isEditView={true} userID={params.userID} userInfo={userInfo} />
</>
) : (
<>
@@ -169,7 +167,7 @@
<div className="user-details">
<Tab.Content>
<Tab.Pane eventKey="edit-basic-info">
- <UserFormComp
+ <UserForm
isEditView={true}
userID={params.userID}
userInfo={userInfo}
@@ -339,4 +337,4 @@
</>
);
}
-export default AddUserView;
+export default EditUserView;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserFormComp.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
similarity index 94%
rename from security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserFormComp.jsx
rename to security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
index 0a76065..2eb9e5a 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserFormComp.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserForm.jsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useReducer, useState } from "react";
+import React, { useReducer } from "react";
import { Button, Row, Col } from "react-bootstrap";
import { Form, Field } from "react-final-form";
import {
@@ -43,8 +43,9 @@
import { useLocation, useNavigate } from "react-router-dom";
import usePrompt from "Hooks/usePrompt";
-const initialState = {
- blockUI: false
+const INITIAL_STATE = {
+ blockUI: false,
+ preventUnBlock: false
};
const PromtDialog = (props) => {
@@ -60,18 +61,25 @@
...state,
blockUI: action.blockUI
};
+ case "SET_PREVENT_ALERT":
+ return {
+ ...state,
+ preventUnBlock: action.preventUnBlock
+ };
default:
throw new Error();
}
}
-function UserFormComp(props) {
- const { state } = useLocation();
+function UserForm(props) {
const navigate = useNavigate();
- const [userFormState, dispatch] = useReducer(reducer, initialState);
- const { blockUI } = userFormState;
+ const { state: navigateState } = useLocation();
+
const { isEditView, userInfo } = props;
- const [preventUnBlock, setPreventUnblock] = useState(false);
+
+ const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
+ const { blockUI, preventUnBlock } = state;
+
const toastId = React.useRef(null);
const isExternalOrFederatedUser =
userInfo?.userSource == UserTypes.USER_EXTERNAL.value ||
@@ -97,7 +105,11 @@
userFormData["status"] = ActivationStatus.ACT_STATUS_ACTIVE.value;
- setPreventUnblock(true);
+ dispatch({
+ type: "SET_PREVENT_ALERT",
+ preventUnBlock: true
+ });
+
if (isEditView) {
let userEditData = { ...userInfo, ...userFormData };
delete userEditData.password;
@@ -148,14 +160,20 @@
data: userFormData
});
- let tblpageData = {};
- if (state && state !== null) {
- tblpageData = state.tblpageData;
- if (state.tblpageData.pageRecords % state.tblpageData.pageSize == 0) {
- tblpageData["totalPage"] = state.tblpageData.totalPage + 1;
+ let tablePageData = {};
+ if (navigateState && navigateState !== null) {
+ tablePageData = navigateState.tablePageData;
+ if (
+ navigateState.tablePageData.pageRecords %
+ navigateState.tablePageData.pageSize ==
+ 0
+ ) {
+ tablePageData["totalPage"] =
+ navigateState.tablePageData.totalPage + 1;
} else {
- if (state !== undefined) {
- tblpageData["totalPage"] = state.tblpageData.totalPage;
+ if (navigateState !== undefined) {
+ tablePageData["totalPage"] =
+ navigateState.tablePageData.totalPage;
}
}
}
@@ -168,7 +186,7 @@
navigate("/users/usertab", {
state: {
showLastPage: true,
- addPageData: tblpageData
+ addPageData: tablePageData
}
});
} catch (error) {
@@ -311,6 +329,7 @@
input.onChange(e);
};
+
const validateForm = (values) => {
const errors = {};
if (!values.name) {
@@ -759,7 +778,10 @@
size="sm"
onClick={() => {
form.reset;
- setPreventUnblock(true);
+ dispatch({
+ type: "SET_PREVENT_ALERT",
+ preventUnBlock: true
+ });
closeForm();
}}
data-id="cancel"
@@ -777,4 +799,4 @@
</>
);
}
-export default UserFormComp;
+export default UserForm;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserListing.jsx b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserListing.jsx
index 77a3c1f..ffce98c 100644
--- a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserListing.jsx
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/UserListing.jsx
@@ -17,7 +17,7 @@
* under the License.
*/
-import React, { useState, useCallback, useRef, useEffect } from "react";
+import React, { useCallback, useRef, useEffect, useReducer } from "react";
import {
Badge,
Button,
@@ -51,47 +51,25 @@
} from "Utils/XAUtils";
import { find, isEmpty, isUndefined, sortBy } from "lodash";
import { getUserAccessRoleList } from "Utils/XAUtils";
-import StructuredFilter from "../../../components/structured-filter/react-typeahead/tokenizer";
-import { BlockUi, Loader } from "../../../components/CommonComponents";
+import StructuredFilter from "Components/structured-filter/react-typeahead/tokenizer";
+import { BlockUi, Loader } from "Components/CommonComponents";
+import { ACTIONS } from "./action";
+import { reducer, INITIAL_STATE } from "./reducer";
-function Users() {
+function UserListing() {
const navigate = useNavigate();
- const { state } = useLocation();
- const [loader, setLoader] = useState(true);
- const [userListingData, setUserData] = useState([]);
- const fetchIdRef = useRef(0);
+ const { state: navigateState, search } = useLocation();
+
+ const isKMSRole = isKeyAdmin() || isKMSAuditor();
+
+ let initialArg = { navigateState: navigateState };
+
+ const [state, dispatch] = useReducer(reducer, initialArg, INITIAL_STATE);
+
+ const [searchParams, setSearchParams] = useSearchParams();
+
const selectedRows = useRef([]);
const toastId = useRef(null);
- const [showModal, setConfirmModal] = useState(false);
- const [showUserSyncDetails, setUserSyncdetails] = useState({
- syncDteails: {},
- showSyncDetails: false
- });
- const [updateTable, setUpdateTable] = useState(moment.now());
- const [totalCount, setTotalCount] = useState(0);
- const [pageCount, setPageCount] = useState(
- state && state.showLastPage ? state.addPageData.totalPage : 0
- );
- const [currentpageIndex, setCurrentPageIndex] = useState(
- state && state.showLastPage ? state.addPageData.totalPage - 1 : 0
- );
- const [currentpageSize, setCurrentPageSize] = useState(
- state && state.showLastPage ? state.addPageData.pageSize : 25
- );
- const [resetPage, setResetPage] = useState({ page: 0 });
- const [tblpageData, setTblPageData] = useState({
- totalPage: 0,
- pageRecords: 0,
- pageSize: 0
- });
- const [searchFilterParams, setSearchFilterParams] = useState([]);
- const [searchParams, setSearchParams] = useSearchParams();
- const [defaultSearchFilterParams, setDefaultSearchFilterParams] = useState(
- []
- );
- const isKMSRole = isKeyAdmin() || isKMSAuditor();
- const [pageLoader, setPageLoader] = useState(true);
- const [blockUI, setBlockUI] = useState(false);
useEffect(() => {
let searchFilterParam = {};
@@ -127,87 +105,164 @@
// Updating the states for search params, search filter and default search filter
setSearchParams({ ...currentParams, ...searchParam }, { replace: true });
if (
- JSON.stringify(searchFilterParams) !== JSON.stringify(searchFilterParam)
+ JSON.stringify(state.searchFilterParams) !==
+ JSON.stringify(searchFilterParam)
) {
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
}
- setDefaultSearchFilterParams(defaultSearchFilterParam);
- setPageLoader(false);
- localStorage.setItem("newDataAdded", state && state.showLastPage);
- }, [searchParams]);
+ dispatch({
+ type: ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS,
+ defaultSearchFilterParams: defaultSearchFilterParam
+ });
+ dispatch({ type: ACTIONS.SET_CONTENT_LOADER, contentLoader: false });
+ localStorage.setItem(
+ "newDataAdded",
+ navigateState && navigateState.showLastPage
+ );
+ }, [search]);
+
useEffect(() => {
if (localStorage.getItem("newDataAdded") == "true") {
- scrollToNewData(userListingData);
+ scrollToNewData(state.tableListingData);
}
- }, [totalCount]);
- const fetchUserInfo = useCallback(
+ }, [state.totalCount]);
+
+ const fetchUsers = useCallback(
async ({ pageSize, pageIndex, gotoPage }) => {
- setLoader(true);
- let userData = [],
- userResp = [];
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: true });
+ let userData = [];
let totalCount = 0;
let page =
- state && state.showLastPage
- ? state.addPageData.totalPage - 1
+ navigateState && navigateState.showLastPage
+ ? navigateState.addPageData.totalPage - 1
: pageIndex;
let totalPageCount = 0;
- const fetchId = ++fetchIdRef.current;
- let params = { ...searchFilterParams };
+ let params = { ...state.searchFilterParams };
+
const userRoleListData = getUserAccessRoleList().map((m) => {
return m.value;
});
- if (fetchId === fetchIdRef.current) {
- params["page"] = page;
+ params["page"] = page;
+ params["startIndex"] =
+ navigateState && navigateState.showLastPage
+ ? (navigateState.addPageData.totalPage - 1) * pageSize
+ : page * pageSize;
+ params["pageSize"] = pageSize;
+ params["userRoleList"] = userRoleListData;
- params["startIndex"] =
- state && state.showLastPage
- ? (state.addPageData.totalPage - 1) * pageSize
- : page * pageSize;
- params["pageSize"] = pageSize;
- params["userRoleList"] = userRoleListData;
- try {
- userResp = await fetchApi({
- url: "xusers/users",
- params: params,
- paramsSerializer: function (params) {
- return qs.stringify(params, { arrayFormat: "repeat" });
- }
- });
- userData = userResp.data.vXUsers;
- totalCount = userResp.data.totalCount;
- totalPageCount = Math.ceil(totalCount / pageSize);
- } catch (error) {
- serverError(error);
- console.error(`Error occurred while fetching User list! ${error}`);
- }
- if (state) {
- state["showLastPage"] = false;
- }
-
- setUserData(userData);
- setTblPageData({
- totalPage: totalPageCount,
- pageRecords: userResp && userResp.data && userResp.data.totalCount,
- pageSize: pageSize
+ try {
+ const response = await fetchApi({
+ url: "xusers/users",
+ params: params,
+ paramsSerializer: function (params) {
+ return qs.stringify(params, { arrayFormat: "repeat" });
+ }
});
- setTotalCount(totalCount);
- setPageCount(totalPageCount);
- setCurrentPageIndex(page);
- setCurrentPageSize(pageSize);
- setResetPage({ page: gotoPage });
- setLoader(false);
+ userData = response.data.vXUsers || [];
+ totalCount = response.data.totalCount || 0;
+ totalPageCount = Math.ceil(totalCount / pageSize);
+ } catch (error) {
+ serverError(error);
+ console.error(`Error occurred while fetching users ! ${error}`);
}
+
+ if (navigateState) {
+ navigateState["showLastPage"] = false;
+ }
+
+ dispatch({
+ type: ACTIONS.SET_TABLE_DATA,
+ tableListingData: userData,
+ totalCount: totalCount,
+ pageCount: totalPageCount,
+ currentPageIndex: page,
+ currentPageSize: pageSize,
+ resetPage: { page: gotoPage },
+ tablePageData: {
+ totalPage: totalPageCount,
+ pageRecords: totalCount,
+ pageSize: pageSize
+ }
+ });
+ dispatch({ type: ACTIONS.SET_TABLE_LOADER, loader: false });
},
- [updateTable, searchFilterParams]
+ [state.refreshTableData]
);
- const handleDeleteBtnClick = () => {
+ const userDelete = () => {
if (selectedRows.current.length > 0) {
- toggleConfirmModal();
+ toggleUserDeleteModal();
} else {
- toast.warning("Please select atleast one user!!");
+ toast.warning("Please select atleast one user !!");
+ }
+ };
+
+ const toggleUserDeleteModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_DELETE_MODAL,
+ showDeleteModal: !state.showDeleteModal
+ });
+ };
+
+ const confirmUserDelete = () => {
+ handleUserDelete();
+ };
+
+ const handleUserDelete = async () => {
+ const selectedData = selectedRows.current;
+ let errorMsg = "";
+ if (selectedData.length > 0) {
+ toggleUserDeleteModal();
+ for (const { original } of selectedData) {
+ try {
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: true });
+ await fetchApi({
+ url: `xusers/secure/users/id/${original.id}`,
+ method: "DELETE",
+ params: {
+ forceDelete: true
+ }
+ });
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
+ } catch (error) {
+ dispatch({ type: ACTIONS.SET_BLOCK_UI, blockUi: false });
+ if (error?.response?.data?.msgDesc) {
+ errorMsg += error.response.data.msgDesc + "\n";
+ } else {
+ errorMsg +=
+ `Error occurred during deleting user: ${original.name}` + "\n";
+ }
+ console.error(errorMsg);
+ }
+ }
+ if (errorMsg) {
+ toast.dismiss(toastId.current);
+ toastId.current = toast.error(errorMsg);
+ } else {
+ toast.dismiss(toastId.current);
+ toastId.current = toast.success("User deleted successfully !");
+ if (
+ (state.tableListingData.length == 1 ||
+ state.tableListingData.length == selectedRows.current.length) &&
+ state.currentPageIndex > 0
+ ) {
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
+ }
+ } else {
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
+ }
+ }
}
};
@@ -225,10 +280,10 @@
toastId.current = toast.warning(
e == VisibilityStatus.STATUS_VISIBLE.value
? `Selected ${
- selectedRows.current.length === 1 ? "User is" : "Users are"
+ selectedRows.current.length === 1 ? "user is" : "users are"
} already visible`
: `Selected ${
- selectedRows.current.length === 1 ? "User is " : "Users are"
+ selectedRows.current.length === 1 ? "user is " : "users are"
} already hidden`
);
return;
@@ -242,66 +297,42 @@
toast.dismiss(toastId.current);
toastId.current = toast.success(
`Sucessfully updated ${
- selectedRows.current.length === 1 ? "User" : "Users"
- } visibility!!`
+ selectedRows.current.length === 1 ? "user" : "users"
+ } visibility !!`
);
- setUpdateTable(moment.now());
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: state.searchFilterParams,
+ refreshTableData: moment.now()
+ });
} catch (error) {
serverError(error);
- console.error(`Error occurred during set User visibility! ${error}`);
+ console.error(`Error occurred during set user visibility ! ${error}`);
}
} else {
toast.dismiss(toastId.current);
- toastId.current = toast.warning("Please select atleast one user!!");
+ toastId.current = toast.warning("Please select atleast one user !!");
}
};
- const handleDeleteClick = async () => {
- const selectedData = selectedRows.current;
- let errorMsg = "";
- if (selectedData.length > 0) {
- toggleConfirmModal();
- for (const { original } of selectedData) {
- try {
- setBlockUI(true);
- await fetchApi({
- url: `xusers/secure/users/id/${original.id}`,
- method: "DELETE",
- params: {
- forceDelete: true
- }
- });
- setBlockUI(false);
- } catch (error) {
- setBlockUI(false);
- if (error?.response?.data?.msgDesc) {
- errorMsg += error.response.data.msgDesc + "\n";
- } else {
- errorMsg +=
- `Error occurred during deleting Users: ${original.name}` + "\n";
- }
- console.error(errorMsg);
- }
- }
- if (errorMsg) {
- toast.dismiss(toastId.current);
- toastId.current = toast.error(errorMsg);
- } else {
- toast.dismiss(toastId.current);
- toastId.current = toast.success("User deleted successfully!");
- if (
- (userListingData.length == 1 ||
- userListingData.length == selectedRows.current.length) &&
- currentpageIndex > 0
- ) {
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
- }
- } else {
- setUpdateTable(moment.now());
- }
- }
- }
+ const addUser = () => {
+ navigate("/user/create", { state: { tablePageData: state.tablePageData } });
+ };
+
+ const openSyncDetailsModal = (value) => {
+ dispatch({
+ type: ACTIONS.SHOW_SYNC_DETAILS_MODAL,
+ showSyncDetailsModal: true,
+ syncDetailsData: !isEmpty(value) && JSON.parse(value)
+ });
+ };
+
+ const hideSyncDetailsModal = () => {
+ dispatch({
+ type: ACTIONS.SHOW_SYNC_DETAILS_MODAL,
+ showSyncDetailsModal: false,
+ syncDetailsData: {}
+ });
};
const columns = React.useMemo(
@@ -331,7 +362,7 @@
},
{
Header: "Email Address",
- accessor: "emailAddress", // accessor is the "key" in the data
+ accessor: "emailAddress",
Cell: (rawValue) => {
if (rawValue.value) {
return (
@@ -443,7 +474,7 @@
{
Header: "Sync Details",
accessor: "otherAttributes",
- Cell: (rawValue, model) => {
+ Cell: (rawValue) => {
if (rawValue.value) {
return (
<div className="text-center">
@@ -453,9 +484,8 @@
data-cy="syncDetailes"
data-for="users"
title="Sync Details"
- id={model.id}
onClick={() => {
- toggleUserSyncModal(rawValue.value);
+ openSyncDetailsModal(rawValue.value);
}}
>
<i className="fa-fw fa fa-eye"> </i>
@@ -472,32 +502,6 @@
[]
);
- const addUser = () => {
- navigate("/user/create", { state: { tblpageData: tblpageData } });
- };
-
- const toggleConfirmModal = () => {
- setConfirmModal((state) => !state);
- };
-
- const toggleUserSyncModal = (raw) => {
- setUserSyncdetails({
- syncDteails: !isEmpty(raw) && JSON.parse(raw),
- showSyncDetails: true
- });
- };
-
- const toggleUserSyncModalClose = () => {
- setUserSyncdetails({
- syncDteails: {},
- showSyncDetails: false
- });
- };
-
- const handleConfirmClick = () => {
- handleDeleteClick();
- };
-
const searchFilterOptions = [
{
category: "emailAddress",
@@ -585,26 +589,31 @@
];
const updateSearchFilter = (filter) => {
- let { searchFilterParam, searchParam } = parseSearchFilter(
+ const { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
- setSearchFilterParams(searchFilterParam);
+ dispatch({
+ type: ACTIONS.SET_SEARCH_FILTER_PARAMS,
+ searchFilterParams: searchFilterParam,
+ refreshTableData: moment.now()
+ });
+
setSearchParams(searchParam, { replace: true });
- if (typeof resetPage?.page === "function") {
- resetPage.page(0);
+ if (typeof state.resetPage?.page === "function") {
+ state.resetPage.page(0);
}
};
return (
<div className="wrap">
- {pageLoader ? (
+ {state.contentLoader ? (
<Loader />
) : (
<React.Fragment>
- <BlockUi isUiBlock={blockUI} />
+ <BlockUi isUiBlock={state.blockUi} />
<Row className="mb-4">
<Col sm={8} className="usr-grp-role-search-width">
<StructuredFilter
@@ -612,7 +621,7 @@
placeholder="Search for your users..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
- defaultSelected={defaultSearchFilterParams}
+ defaultSelected={state.defaultSearchFilterParams}
/>
</Col>
{isSystemAdmin() && (
@@ -642,7 +651,7 @@
variant="danger"
size="sm"
title="Delete"
- onClick={handleDeleteBtnClick}
+ onClick={userDelete}
className="ms-1 btn-sm"
data-id="deleteUserGroup"
data-cy="deleteUserGroup"
@@ -654,15 +663,15 @@
</Row>
<XATableLayout
- data={userListingData}
+ data={state.tableListingData}
columns={columns}
- fetchData={fetchUserInfo}
- totalCount={totalCount}
- pageCount={pageCount}
- currentpageIndex={currentpageIndex}
- currentpageSize={currentpageSize}
+ fetchData={fetchUsers}
+ totalCount={state.totalCount}
+ pageCount={state.pageCount}
+ currentpageIndex={state.currentPageIndex}
+ currentpageSize={state.currentPageSize}
pagination
- loading={loader}
+ loading={state.loader}
rowSelectOp={
(isSystemAdmin() || isKeyAdmin()) && {
position: "first",
@@ -674,7 +683,7 @@
})}
/>
- <Modal show={showModal} onHide={toggleConfirmModal}>
+ <Modal show={state.showDeleteModal} onHide={toggleUserDeleteModal}>
<Modal.Header closeButton>
<span className="text-word-break">
Are you sure you want to delete the
@@ -694,18 +703,18 @@
<Button
variant="secondary"
size="sm"
- onClick={toggleConfirmModal}
+ onClick={toggleUserDeleteModal}
>
Close
</Button>
- <Button variant="primary" size="sm" onClick={handleConfirmClick}>
+ <Button variant="primary" size="sm" onClick={confirmUserDelete}>
OK
</Button>
</Modal.Footer>
</Modal>
<Modal
- show={showUserSyncDetails && showUserSyncDetails.showSyncDetails}
- onHide={toggleUserSyncModalClose}
+ show={state.showSyncDetailsModal}
+ onHide={hideSyncDetailsModal}
size="xl"
>
<Modal.Header>
@@ -713,14 +722,14 @@
</Modal.Header>
<Modal.Body>
<SyncSourceDetails
- syncDetails={showUserSyncDetails.syncDteails}
+ syncDetails={state.syncDetailsData}
></SyncSourceDetails>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
size="sm"
- onClick={toggleUserSyncModalClose}
+ onClick={hideSyncDetailsModal}
>
OK
</Button>
@@ -732,4 +741,4 @@
);
}
-export default Users;
+export default UserListing;
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/action.js b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/action.js
new file mode 100644
index 0000000..a16d899
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/action.js
@@ -0,0 +1,29 @@
+/*
+ * 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.
+ */
+
+export const ACTIONS = {
+ SET_TABLE_LOADER: "set-table-loader",
+ SET_CONTENT_LOADER: "set-content-loader",
+ SET_SEARCH_FILTER_PARAMS: "set-search-filter-params",
+ SET_DEFAULT_SEARCH_FILTER_PARAMS: "set-default-search-filter-params",
+ SET_TABLE_DATA: "set-table-data",
+ SHOW_DELETE_MODAL: "show-delete-modal",
+ SHOW_SYNC_DETAILS_MODAL: "show-sync-details-modal",
+ SET_BLOCK_UI: "set-block-ui"
+};
diff --git a/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/reducer.js b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/reducer.js
new file mode 100644
index 0000000..7b0131f
--- /dev/null
+++ b/security-admin/src/main/webapp/react-webapp/src/views/UserGroupRoleListing/users_details/reducer.js
@@ -0,0 +1,110 @@
+/*
+ * 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 moment from "moment-timezone";
+import { ACTIONS } from "./action";
+
+export const INITIAL_STATE = (initialArg) => {
+ return {
+ loader: true,
+ contentLoader: true,
+ searchFilterParams: [],
+ defaultSearchFilterParams: [],
+ tableListingData: [],
+ totalCount: 0,
+ pageCount:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage
+ : 0,
+ currentPageIndex:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.totalPage - 1
+ : 0,
+ currentPageSize:
+ initialArg.navigateState && initialArg.navigateState.showLastPage
+ ? initialArg.navigateState.addPageData.pageSize
+ : 25,
+ resetPage: { page: 0 },
+ tablePageData: {
+ totalPage: 0,
+ pageRecords: 0,
+ pageSize: 25
+ },
+ refreshTableData: moment.now(),
+ showDeleteModal: false,
+ showSyncDetailsModal: false,
+ syncDetailsData: {},
+ blockUi: false
+ };
+};
+
+export const reducer = (state, action) => {
+ switch (action.type) {
+ case ACTIONS.SET_TABLE_LOADER:
+ return {
+ ...state,
+ loader: action.loader
+ };
+ case ACTIONS.SET_CONTENT_LOADER:
+ return {
+ ...state,
+ contentLoader: action.contentLoader
+ };
+ case ACTIONS.SET_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ searchFilterParams: action.searchFilterParams,
+ refreshTableData: action.refreshTableData
+ };
+ case ACTIONS.SET_DEFAULT_SEARCH_FILTER_PARAMS:
+ return {
+ ...state,
+ defaultSearchFilterParams: action.defaultSearchFilterParams
+ };
+ case ACTIONS.SET_TABLE_DATA:
+ return {
+ ...state,
+ tableListingData: action.tableListingData,
+ totalCount: action.totalCount,
+ pageCount: action.pageCount,
+ currentPageIndex: action.currentPageIndex,
+ currentPageSize: action.currentPageSize,
+ resetPage: action.resetPage,
+ tablePageData: action.tablePageData
+ };
+ case ACTIONS.SHOW_DELETE_MODAL:
+ return {
+ ...state,
+ showDeleteModal: action.showDeleteModal
+ };
+ case ACTIONS.SHOW_SYNC_DETAILS_MODAL:
+ return {
+ ...state,
+ showSyncDetailsModal: action.showSyncDetailsModal,
+ syncDetailsData: action.syncDetailsData
+ };
+ case ACTIONS.SET_BLOCK_UI:
+ return {
+ ...state,
+ blockUi: action.blockUi
+ };
+ default:
+ return state;
+ }
+};