Skip to content

Commit

Permalink
Fixed some details on audit logs page (#1156)
Browse files Browse the repository at this point in the history
- Changed default port to 5005 due 5000 port is not available to use in new MacOS versions

- Added an option to show full log information in a modal

- Fixed issue with column selector dropdown & mui v5

- Fixed advanced filters table population

- Changed date range selector picker for audit logs

Signed-off-by: Benjamin Perez <benjamin@bexsoft.net>

Co-authored-by: Benjamin Perez <benjamin@bexsoft.net>
  • Loading branch information
bexsoft and Benjamin Perez committed Oct 27, 2021
1 parent 5f1e228 commit 5740c11
Show file tree
Hide file tree
Showing 6 changed files with 204 additions and 43 deletions.
2 changes: 1 addition & 1 deletion portal-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
"websocket": "^1.0.31"
},
"scripts": {
"start": "PORT=5000 react-app-rewired start",
"start": "PORT=5005 react-app-rewired start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ interface IDateRangeSelector {
setTimeStart: (date: any) => void;
timeEnd: any;
setTimeEnd: (date: any) => void;
triggerSync: () => void;
triggerSync?: () => void;
}

const styles = (theme: Theme) =>
Expand Down Expand Up @@ -97,16 +97,18 @@ const DateRangeSelector = ({
noInputIcon
/>
</div>
<Button
type="button"
variant="contained"
color="primary"
onClick={triggerSync}
endIcon={<SyncIcon />}
className={classes.syncButton}
>
Sync
</Button>
{triggerSync && (
<Button
type="button"
variant="contained"
color="primary"
onClick={triggerSync}
endIcon={<SyncIcon />}
className={classes.syncButton}
>
Sync
</Button>
)}
</Grid>
</Fragment>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,6 @@ const styles = () =>
right: 0,
top: 0,
},
popoverContainer: {
position: "relative",
},
popoverContent: {
maxHeight: 250,
overflowY: "auto",
Expand Down Expand Up @@ -573,7 +570,6 @@ const TableWrapper = ({
horizontal: "left",
}}
onClose={closeColumnSelector}
className={classes.popoverContainer}
>
<div className={classes.shownColumnsLabel}>Shown Columns</div>
<div className={classes.popoverContent}>
Expand Down
100 changes: 100 additions & 0 deletions portal-ui/src/screens/Console/Logs/LogSearch/LogSearchFullModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

import React, { Fragment } from "react";
import get from "lodash/get";
import { Button, Grid } from "@mui/material";
import { Theme } from "@mui/material/styles";
import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import ModalWrapper from "../../Common/ModalWrapper/ModalWrapper";
import { modalBasic } from "../../Common/FormComponents/common/styleLibrary";
import { IReqInfoSearchResults } from "./types";
import { LogSearchColumnLabels } from "./utils";

interface ILogSearchFullModal {
modalOpen: boolean;
logSearchElement: IReqInfoSearchResults;
onClose: () => void;
classes: any;
}

const styles = (theme: Theme) =>
createStyles({
buttonContainer: {
textAlign: "right",
},
pathLabel: {
marginTop: 0,
marginBottom: 32,
},
objectKeyCol: {
fontWeight: 700,
paddingRight: "10px",
textAlign: "left",
},
...modalBasic,
});

const LogSearchFullModal = ({
modalOpen,
logSearchElement,
onClose,
classes,
}: ILogSearchFullModal) => {
const jsonItems = Object.keys(logSearchElement);

return (
<Fragment>
<ModalWrapper
modalOpen={modalOpen}
title="Full Log Information"
onClose={() => {
onClose();
}}
>
<Grid container>
<Grid item xs={12}>
<table>
<tbody>
{jsonItems.map((objectKey: string, index: number) => (
<tr key={`logSearch-${index.toString()}`}>
<th className={classes.objectKeyCol}>
{get(LogSearchColumnLabels, objectKey, `${objectKey}`)}
</th>
<td>{get(logSearchElement, objectKey, "")}</td>
</tr>
))}
</tbody>
</table>
</Grid>
<Grid item xs={12} className={classes.buttonContainer}>
<Button
type="button"
variant="contained"
color="primary"
onClick={onClose}
>
Close
</Button>
</Grid>
</Grid>
</ModalWrapper>
</Fragment>
);
};

export default withStyles(styles)(LogSearchFullModal);
87 changes: 60 additions & 27 deletions portal-ui/src/screens/Console/Logs/LogSearch/LogsSearchMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ import api from "../../../../common/api";
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
import FilterInputWrapper from "../../Common/FormComponents/FilterInputWrapper/FilterInputWrapper";
import DateTimePickerWrapper from "../../Common/FormComponents/DateTimePickerWrapper/DateTimePickerWrapper";
import LogSearchFullModal from "./LogSearchFullModal";
import { LogSearchColumnLabels } from "./utils";
import DateRangeSelector from "../../Common/FormComponents/DateRangeSelector/DateRangeSelector";

interface ILogSearchProps {
classes: any;
Expand Down Expand Up @@ -154,6 +157,10 @@ const LogsSearchMain = ({
]);
const [nextPage, setNextPage] = useState<number>(0);
const [alreadyFetching, setAlreadyFetching] = useState<boolean>(false);
const [logSearchExtrasOpen, setLogSearchExtrasOpen] =
useState<boolean>(false);
const [selectedItem, setSelectedItem] =
useState<IReqInfoSearchResults | null>(null);

let recordsResp: any = null;
const logSearchEnabled = features && features.includes("log-search");
Expand Down Expand Up @@ -188,11 +195,10 @@ const LogsSearchMain = ({
)
.then((res: ISearchResponse) => {
const fetchedResults = res.results || [];
const newResultSet = [...records, ...fetchedResults];

setLoading(false);
setAlreadyFetching(false);
setRecords(newResultSet);
setRecords(fetchedResults);
setNextPage(nextPage + 1);

if (recordsResp !== null) {
Expand All @@ -218,7 +224,6 @@ const LogsSearchMain = ({
sortOrder,
timeStart,
timeEnd,
records,
recordsResp,
setErrorSnackMessage,
]);
Expand Down Expand Up @@ -262,27 +267,36 @@ const LogsSearchMain = ({
});
};

const openExtraInformation = (item: IReqInfoSearchResults) => {
setSelectedItem(item);
setLogSearchExtrasOpen(true);
};

const closeViewExtraInformation = () => {
setSelectedItem(null);
setLogSearchExtrasOpen(false);
};

return (
<Fragment>
{logSearchExtrasOpen && selectedItem !== null && (
<LogSearchFullModal
logSearchElement={selectedItem}
modalOpen={logSearchExtrasOpen}
onClose={closeViewExtraInformation}
/>
)}
<Grid container className={classes.logsSubContainer}>
<Grid
item
xs={12}
className={`${classes.actionsTray} ${classes.timeContainers}`}
>
<span className={classes.label}>Start Time</span>
<DateTimePickerWrapper
value={timeStart}
onChange={setTimeStart}
forSearchBlock
id="stTime"
/>
<span className={classes.label}>End Time</span>
<DateTimePickerWrapper
value={timeEnd}
onChange={setTimeEnd}
forSearchBlock
id="endTime"
<DateRangeSelector
setTimeEnd={setTimeEnd}
setTimeStart={setTimeStart}
timeEnd={timeEnd}
timeStart={timeStart}
/>
</Grid>
<Grid item xs={12} className={`${classes.advancedLabelContainer}`}>
Expand Down Expand Up @@ -376,15 +390,28 @@ const LogsSearchMain = ({
<Grid item xs={12}>
<TableWrapper
columns={[
{ label: "Timestamp", elementKey: "time", enableSort: true },
{ label: "API Name", elementKey: "api_name" },
{ label: "Bucket", elementKey: "bucket" },
{ label: "Object", elementKey: "object" },
{ label: "Remote Host", elementKey: "remote_host" },
{ label: "Request ID", elementKey: "request_id" },
{ label: "User Agent", elementKey: "user_agent" },
{
label: "Response Status",
label: LogSearchColumnLabels.time,
elementKey: "time",
enableSort: true,
},
{ label: LogSearchColumnLabels.api_name, elementKey: "api_name" },
{ label: LogSearchColumnLabels.bucket, elementKey: "bucket" },
{ label: LogSearchColumnLabels.object, elementKey: "object" },
{
label: LogSearchColumnLabels.remote_host,
elementKey: "remote_host",
},
{
label: LogSearchColumnLabels.request_id,
elementKey: "request_id",
},
{
label: LogSearchColumnLabels.user_agent,
elementKey: "user_agent",
},
{
label: LogSearchColumnLabels.response_status,
elementKey: "response_status",
renderFunction: (element) => (
<Fragment>
Expand All @@ -396,17 +423,17 @@ const LogsSearchMain = ({
renderFullObject: true,
},
{
label: "Request Content Length",
label: LogSearchColumnLabels.request_content_length,
elementKey: "request_content_length",
renderFunction: niceBytes,
},
{
label: "Response Content Length",
label: LogSearchColumnLabels.response_content_length,
elementKey: "response_content_length",
renderFunction: niceBytes,
},
{
label: "Time to Response NS",
label: LogSearchColumnLabels.time_to_response_ns,
elementKey: "time_to_response_ns",
renderFunction: nsToSeconds,
contentTextAlign: "right",
Expand All @@ -432,6 +459,12 @@ const LogsSearchMain = ({
recordsCount: 1000000,
loadMoreRecords: loadMoreRecords,
}}
itemActions={[
{
type: "view",
onClick: openExtraInformation,
},
]}
textSelectable
/>
</Grid>
Expand Down
30 changes: 30 additions & 0 deletions portal-ui/src/screens/Console/Logs/LogSearch/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// This file is part of MinIO Console Server
// Copyright (c) 2021 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.

export const LogSearchColumnLabels = {
time: "Timestamp",
api_name: "API Name",
bucket: "Bucket",
object: "Object",
remote_host: "Remote Host",
request_id: "Request ID",
user_agent: "User Agent",
response_status: "Response Status",
response_status_code: "Response Status Code",
request_content_length: "Request Content Length",
response_content_length: "Response Content Length",
time_to_response_ns: "Time to Response NS",
};

0 comments on commit 5740c11

Please sign in to comment.