blob: d73e81f2340667d37f79c77493a6a467b18e6a1e [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import React, { useState, useCallback, useRef, useEffect } from "react";
import { useSearchParams, useNavigate } 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 dateFormat from "dateformat";
import AdminModal from "./AdminModal";
import { AuditFilterEntries } from "Components/CommonComponents";
import OperationAdminModal from "./OperationAdminModal";
import moment from "moment-timezone";
import { capitalize, startCase, sortBy, toLower } from "lodash";
import StructuredFilter from "../../components/structured-filter/react-typeahead/tokenizer";
import {
getTableSortBy,
getTableSortType,
fetchSearchFilterParams,
parseSearchFilter,
serverError
} from "../../utils/XAUtils";
import { Loader } from "../../components/CommonComponents";
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);
const navigate = useNavigate();
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 } =
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)
) {
setSearchFilterParams(searchFilterParam);
}
setDefaultSearchFilterParams(defaultSearchFilterParam);
localStorage.setItem("admin", JSON.stringify(searchParam));
setContentLoader(false);
}, [searchParams]);
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);
}
},
[updateTable, searchFilterParams]
);
const refreshTable = () => {
setAdminLogs([]);
setLoader(true);
setUpdateTable(moment.now());
};
const openModal = (sessionId) => {
setShowModal(true);
setSessionId(sessionId);
};
const columns = React.useMemo(
() => [
{
Header: "Operation",
accessor: "operation",
Cell: (rawValue) => {
let classtype = rawValue.row.original.objectClassType;
let action = rawValue.row.original.action;
let objectname = rawValue.row.original.objectName;
let operation = "";
let hasAction = [
"EXPORT JSON",
"EXPORT EXCEL",
"EXPORT CSV",
"IMPORT START",
"IMPORT END"
];
if (hasAction.includes(action)) {
if (
action == "EXPORT JSON" ||
action == "EXPORT EXCEL" ||
action == "EXPORT CSV"
)
return "Exported policies";
else return action;
} else {
if (
classtype == ClassTypes.CLASS_TYPE_XA_ASSET.value ||
classtype == ClassTypes.CLASS_TYPE_RANGER_SERVICE.value
)
operation = (
<span>
Service {action}d <strong>{objectname}</strong>
</span>
);
else if (
classtype == ClassTypes.CLASS_TYPE_XA_RESOURCE.value ||
classtype == ClassTypes.CLASS_TYPE_RANGER_POLICY.value
)
operation = (
<span>
Policy {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_XA_USER.value)
operation = (
<span>
User {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_XA_GROUP.value)
operation = (
<span>
Group {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_USER_PROFILE.value)
operation = (
<span>
User profile {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_PASSWORD_CHANGE.value)
operation = (
<span>
User profile {action}d <strong>{objectname}</strong>
</span>
);
else if (
classtype == ClassTypes.CLASS_TYPE_RANGER_SECURITY_ZONE.value
)
operation = (
<span>
Security Zone {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_ROLE.value)
operation = (
<span>
Role {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_DATASET.value)
operation = (
<span>
Dataset {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_PROJECT.value)
operation = (
<span>
Project {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_DATA_SHARE.value)
operation = (
<span>
Data Share {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_SHARED_RESOURCE.value)
operation = (
<span>
Shared Resource {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_DATA_SHARE_IN_DATASET.value)
operation = (
<span>
DataShare in Dataset {action}d <strong>{objectname}</strong>
</span>
);
else if (classtype == ClassTypes.CLASS_TYPE_RANGER_DATASET_IN_PROJECT.value)
operation = (
<span>
Dataset in Project {action}d <strong>{objectname}</strong>
</span>
);
return <div className="text-truncate">{operation}</div>;
}
},
disableSortBy: true
},
{
Header: "Audit Type",
accessor: "objectClassType",
Cell: (rawValue) => {
let classtype = rawValue.row.original.objectClassType;
var audittype = enumValueToLabel(ClassTypes, classtype);
return (
<div className="text-center">{Object.values(audittype.label)}</div>
);
},
disableSortBy: true
},
{
Header: "User",
accessor: "owner",
Cell: (rawValue) => {
return rawValue.value !== undefined ? (
<span className="text-center d-block">{rawValue.value}</span>
) : (
<span className="text-center d-block">--</span>
);
},
disableSortBy: true
},
{
Header: "Date ( India Standard Time )",
accessor: "createDate",
Cell: (rawValue) => {
const date = rawValue.value;
const newdate = dateFormat(date, "mm/dd/yyyy hh:MM:ss TT");
return <span className="text-center d-block">{newdate}</span>;
}
},
{
Header: "Actions",
accessor: "action",
Cell: (rawValue) => {
var operation = "";
if (rawValue.value == "create") {
operation = (
<span className="text-center d-block">
<Badge variant="success">{capitalize(rawValue.value)}</Badge>
</span>
);
} else if (rawValue.value == "update") {
operation = (
<span className="text-center d-block">
<Badge variant="warning">{capitalize(rawValue.value)}</Badge>
</span>
);
} else if (rawValue.value == "delete") {
operation = (
<span className="text-center d-block">
<Badge variant="danger">{capitalize(rawValue.value)}</Badge>
</span>
);
} else if (rawValue.value == "IMPORT START") {
operation = (
<span className="text-center d-block">
<Badge variant="info">{capitalize(rawValue.value)}</Badge>
</span>
);
} else if (rawValue.value == "IMPORT END") {
operation = (
<span className="text-center d-block">
<Badge variant="info">{capitalize(rawValue.value)}</Badge>
</span>
);
} else {
operation = (
<span className="text-center d-block">
<Badge variant="secondary">
{startCase(toLower(rawValue.value))}
</Badge>{" "}
</span>
);
}
return operation;
},
disableSortBy: true
},
{
Header: "Session ID",
accessor: "sessionId",
Cell: (rawValue) => {
var sessionId = rawValue.value;
if (sessionId != undefined) {
return (
<span className="text-center d-block">
<a
role="button"
className="text-primary"
onClick={(e) => {
e.stopPropagation();
openModal(sessionId);
}}
data-id={sessionId}
data-cy={sessionId}
title={sessionId}
>
{sessionId}
</a>
</span>
);
} else {
return <span className="text-center d-block">--</span>;
}
},
disableSortBy: true
}
],
[]
);
const getDefaultSort = React.useMemo(
() => [
{
id: "createDate",
desc: true
}
],
[]
);
const updateSearchFilter = (filter) => {
let { searchFilterParam, searchParam } = parseSearchFilter(
filter,
searchFilterOptions
);
setSearchFilterParams(searchFilterParam);
setSearchParams(searchParam, { replace: true });
localStorage.setItem("admin", JSON.stringify(searchParam));
if (typeof resetPage?.page === "function") {
resetPage.page(0);
}
};
const searchFilterOptions = [
{
category: "action",
label: "Actions",
urlLabel: "actions",
type: "textoptions",
options: () => {
return [
{ value: "create", label: "Create" },
{ value: "update", label: "Update" },
{ value: "delete", label: "Delete" },
{ value: "password change", label: "Password Change" },
{ value: "EXPORT JSON", label: "Export Json" },
{ value: "EXPORT CSV", label: "Export Csv" },
{ value: "EXPORT EXCEL", label: "Export Excel" },
{ value: "IMPORT END", label: "Import End" },
{ value: "IMPORT START", label: "Import Start" },
{ value: "Import Create", label: "Import Create" },
{ value: "Import Delete", label: "Import Delete" }
];
}
},
{
category: "objectClassType",
label: "Audit Type",
urlLabel: "auditType",
type: "textoptions",
options: () => {
return [
{ value: "1020", label: "Ranger Policy" },
{ value: "1002", label: "Ranger Group" },
{ value: "1056", label: "Ranger Security Zone" },
{ value: "1030", label: "Ranger Service" },
{ value: "1003", label: "Ranger User" },
{ value: "1062", label: "Ranger Dataset" },
{ value: "1063", label: "Ranger Project" },
{ value: "1064", label: "Ranger Data Share" },
{ value: "1065", label: "Ranger Shared Resource" },
{ value: "1066", label: "Ranger Data Share in Dataset" },
{ value: "1067", label: "Ranger Dataset in Project" },
{ value: "2", label: "User Profile" }
];
}
},
{
category: "endDate",
label: "End Date",
urlLabel: "endDate",
type: "date"
},
{
category: "sessionId",
label: "Session ID",
urlLabel: "sessionId",
type: "text"
},
{
category: "startDate",
label: "Start Date",
urlLabel: "startDate",
type: "date"
},
{
category: "owner",
label: "User",
urlLabel: "user",
type: "text"
}
];
return contentLoader ? (
<Loader />
) : (
<div className="wrap">
<React.Fragment>
<Row className="mb-2">
<Col sm={12}>
<div className="searchbox-border">
<StructuredFilter
key="admin-log-search-filter"
placeholder="Search for your access logs..."
options={sortBy(searchFilterOptions, ["label"])}
onChange={updateSearchFilter}
defaultSelected={defaultSearchFilterParams}
/>
</div>
</Col>
</Row>
<AuditFilterEntries entries={entries} refreshTable={refreshTable} />
<XATableLayout
data={adminListingData}
columns={columns}
fetchData={fetchAdminLogsInfo}
totalCount={entries && entries.totalCount}
pageCount={pageCount}
loading={loader}
columnSort={true}
defaultSort={getDefaultSort}
getRowProps={(row) => ({
onClick: () => rowModal(row)
})}
/>
<AdminModal
show={showmodal}
data={sessionId}
onHide={handleClose}
updateSessionId={updateSessionId}
></AdminModal>
<OperationAdminModal
show={showrowmodal}
data={rowdata}
onHide={handleClosed}
></OperationAdminModal>
</React.Fragment>
</div>
);
}
export default Admin;