Fix 1299: Tools menu not showing for Heal Only Policy (#1301)

* Fix 1299: Tools menu not showing for Heal Only Policy

* Fix caching issue

Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
Daniel Valdivia
2021-12-07 13:38:36 -08:00
committed by GitHub
parent dfcd49bb5d
commit 1e59f131e8
11 changed files with 121 additions and 159 deletions

View File

@@ -122,6 +122,9 @@ export const IAM_SCOPES = {
ADMIN_DELETE_POLICY: "admin:DeletePolicy",
ADMIN_ATTACH_USER_OR_GROUP_POLICY: "admin:AttachUserOrGroupPolicy",
ADMIN_HEAL_ACTION: "admin:Heal",
ADMIN_HEALTH_ACTION: "admin:OBDInfo",
ADMIN_CONSOLE_LOG_ACTION: "admin:ConsoleLog",
ADMIN_TRACE_ACTION: "admin:ServerTrace",
S3_ALL_ACTIONS: "s3:*",
ADMIN_ALL_ACTIONS: "admin:*",
};

View File

@@ -1,44 +0,0 @@
// 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 * as React from "react";
import { SVGProps } from "react";
const DiagnosticIcon = (props: SVGProps<SVGSVGElement>) => (
<svg
xmlns="http://www.w3.org/2000/svg"
className={`min-icon`}
fill={"currentcolor"}
viewBox="0 0 256 256"
{...props}
>
<defs>
<clipPath id="prefix__a">
<path d="M0 0h256v256H0z" />
</clipPath>
</defs>
<g clipPath="url(#prefix__a)">
<path fill="none" d="M0 0h256v256H0z" />
<path
data-name="Uni\xF3n 17"
d="M.449 128.494A128.188 128.188 0 0 1 128.494.45h10.6v52.857a76.1 76.1 0 0 1 46.531 25.151 75.572 75.572 0 0 1 13.854 22.845 75.251 75.251 0 0 1 5.039 27.189 76.11 76.11 0 0 1-76.023 76.022 76.1 76.1 0 0 1-76.012-76.022 75.291 75.291 0 0 1 5.037-27.189 75.678 75.678 0 0 1 13.85-22.845 76.135 76.135 0 0 1 46.555-25.151v-31.18a106.369 106.369 0 0 0-19.6 3.814 106.378 106.378 0 0 0-18.193 7.25 107.579 107.579 0 0 0-16.385 10.312A108.253 108.253 0 0 0 49.54 56.524a108.229 108.229 0 0 0-11.676 15.37 107.348 107.348 0 0 0-8.787 17.356 106.17 106.17 0 0 0-7.459 39.244 107.008 107.008 0 0 0 106.877 106.892 107.017 107.017 0 0 0 106.9-106.892 10.5 10.5 0 0 1 3.1-7.479 10.49 10.49 0 0 1 7.475-3.1 10.593 10.593 0 0 1 10.584 10.58 128.2 128.2 0 0 1-128.057 128.057A128.2 128.2 0 0 1 .449 128.494Zm99.967-47.048a55.106 55.106 0 0 0-14.062 12.016 54.643 54.643 0 0 0-9.336 16.083 54.492 54.492 0 0 0-3.379 18.95 54.464 54.464 0 0 0 4.316 21.333 54.924 54.924 0 0 0 5.068 9.317 55.648 55.648 0 0 0 6.7 8.12 55.546 55.546 0 0 0 8.125 6.7 54.955 54.955 0 0 0 9.316 5.068 54.353 54.353 0 0 0 21.328 4.316 54.917 54.917 0 0 0 54.854-54.857 54.492 54.492 0 0 0-3.379-18.95 54.614 54.614 0 0 0-9.326-16.083 55.144 55.144 0 0 0-14.049-12.016 54.571 54.571 0 0 0-17.5-6.723v30.482a25.816 25.816 0 0 1 10.824 9.254 25.366 25.366 0 0 1 4.211 14.035 25.433 25.433 0 0 1-2.014 9.982 25.524 25.524 0 0 1-5.494 8.145 25.5 25.5 0 0 1-8.145 5.493 25.518 25.518 0 0 1-9.982 2.015 25.477 25.477 0 0 1-9.973-2.015 25.621 25.621 0 0 1-8.148-5.493 25.538 25.538 0 0 1-5.488-8.145 25.522 25.522 0 0 1-2.016-9.982 25.393 25.393 0 0 1 4.207-14.035 25.82 25.82 0 0 1 10.848-9.254V74.72a54.537 54.537 0 0 0-17.508 6.73Z"
/>
<path data-name="Rect\xE1ngulo 878" fill="none" d="M0 0h256v256H0z" />
</g>
</svg>
);
export default DiagnosticIcon;

View File

@@ -19,17 +19,25 @@ import React, { SVGProps } from "react";
const DiagnosticsIcon = (props: SVGProps<SVGSVGElement>) => {
return (
<svg
{...props}
xmlns="http://www.w3.org/2000/svg"
className={`min-icon`}
fill={"currentcolor"}
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 10.405 10.405"
viewBox="0 0 256 256"
{...props}
>
<path
d="M9.932 4.778a.424.424 0 00-.424.424 4.31 4.31 0 01-4.305 4.3 4.309 4.309 0 01-4.3-4.3A4.311 4.311 0 014.784.918v1.259A3.06 3.06 0 002.15 5.202 3.062 3.062 0 005.208 8.26a3.062 3.062 0 003.058-3.058 3.06 3.06 0 00-2.634-3.025V.049h-.424A5.158 5.158 0 00.055 5.201a5.158 5.158 0 005.153 5.153 5.158 5.158 0 005.153-5.153.424.424 0 00-.429-.423zm-2.519.424a2.213 2.213 0 01-2.21 2.21 2.213 2.213 0 01-2.21-2.21A2.213 2.213 0 014.78 3.035v1.231a1.028 1.028 0 00-.606.936 1.03 1.03 0 001.03 1.03 1.03 1.03 0 001.03-1.03 1.028 1.028 0 00-.605-.936V3.035a2.212 2.212 0 011.784 2.167z"
stroke="#000"
strokeWidth={0.1}
/>
<defs>
<clipPath id="prefix__a">
<path d="M0 0h256v256H0z" />
</clipPath>
</defs>
<g clipPath="url(#prefix__a)">
<path fill="none" d="M0 0h256v256H0z" />
<path
data-name="Uni\xF3n 17"
d="M.449 128.494A128.188 128.188 0 0 1 128.494.45h10.6v52.857a76.1 76.1 0 0 1 46.531 25.151 75.572 75.572 0 0 1 13.854 22.845 75.251 75.251 0 0 1 5.039 27.189 76.11 76.11 0 0 1-76.023 76.022 76.1 76.1 0 0 1-76.012-76.022 75.291 75.291 0 0 1 5.037-27.189 75.678 75.678 0 0 1 13.85-22.845 76.135 76.135 0 0 1 46.555-25.151v-31.18a106.369 106.369 0 0 0-19.6 3.814 106.378 106.378 0 0 0-18.193 7.25 107.579 107.579 0 0 0-16.385 10.312A108.253 108.253 0 0 0 49.54 56.524a108.229 108.229 0 0 0-11.676 15.37 107.348 107.348 0 0 0-8.787 17.356 106.17 106.17 0 0 0-7.459 39.244 107.008 107.008 0 0 0 106.877 106.892 107.017 107.017 0 0 0 106.9-106.892 10.5 10.5 0 0 1 3.1-7.479 10.49 10.49 0 0 1 7.475-3.1 10.593 10.593 0 0 1 10.584 10.58 128.2 128.2 0 0 1-128.057 128.057A128.2 128.2 0 0 1 .449 128.494Zm99.967-47.048a55.106 55.106 0 0 0-14.062 12.016 54.643 54.643 0 0 0-9.336 16.083 54.492 54.492 0 0 0-3.379 18.95 54.464 54.464 0 0 0 4.316 21.333 54.924 54.924 0 0 0 5.068 9.317 55.648 55.648 0 0 0 6.7 8.12 55.546 55.546 0 0 0 8.125 6.7 54.955 54.955 0 0 0 9.316 5.068 54.353 54.353 0 0 0 21.328 4.316 54.917 54.917 0 0 0 54.854-54.857 54.492 54.492 0 0 0-3.379-18.95 54.614 54.614 0 0 0-9.326-16.083 55.144 55.144 0 0 0-14.049-12.016 54.571 54.571 0 0 0-17.5-6.723v30.482a25.816 25.816 0 0 1 10.824 9.254 25.366 25.366 0 0 1 4.211 14.035 25.433 25.433 0 0 1-2.014 9.982 25.524 25.524 0 0 1-5.494 8.145 25.5 25.5 0 0 1-8.145 5.493 25.518 25.518 0 0 1-9.982 2.015 25.477 25.477 0 0 1-9.973-2.015 25.621 25.621 0 0 1-8.148-5.493 25.538 25.538 0 0 1-5.488-8.145 25.522 25.522 0 0 1-2.016-9.982 25.393 25.393 0 0 1 4.207-14.035 25.82 25.82 0 0 1 10.848-9.254V74.72a54.537 54.537 0 0 0-17.508 6.73Z"
/>
<path data-name="Rect\xE1ngulo 878" fill="none" d="M0 0h256v256H0z" />
</g>
</svg>
);
};

View File

@@ -34,7 +34,6 @@ export { default as CopyIcon } from "./CopyIcon";
export { default as CreateIcon } from "./CreateIcon";
export { default as DashboardIcon } from "./DashboardIcon";
export { default as DeleteIcon } from "./DeleteIcon";
export { default as DiagnosticIcon } from "./DiagnosticIcon";
export { default as DiagnosticsIcon } from "./DiagnosticsIcon";
export { default as DocumentationIcon } from "./DocumentationIcon";
export { default as DownloadIcon } from "./DownloadIcon";

View File

@@ -41,7 +41,6 @@ import {
CreateIcon,
DashboardIcon,
DeleteIcon,
DiagnosticIcon,
DiagnosticsIcon,
DocumentationIcon,
DownloadIcon,
@@ -225,10 +224,6 @@ const IconsScreen = ({ classes }: IIconsScreenSimple) => {
<DeleteIcon /> <br />
DeleteIcon
</Grid>
<Grid item xs={3} sm={2} md={1}>
<DiagnosticIcon /> <br />
DiagnosticIcon
</Grid>
<Grid item xs={3} sm={2} md={1}>
<DiagnosticsIcon /> <br />
DiagnosticsIcon

View File

@@ -270,6 +270,9 @@ const Console = ({
const allowedPages = !session
? []
: session.pages.reduce((result: any, item: any, index: any) => {
if (item.startsWith("/tools")) {
result["/tools"] = true;
}
result[item] = true;
return result;
}, {});

View File

@@ -42,14 +42,12 @@ import api from "../../../common/api";
import MenuIcon from "@mui/icons-material/Menu";
import LogoutIcon from "../../../icons/LogoutIcon";
import { resetSession } from "../actions";
const drawerWidth = 245;
const BucketsIcon = React.lazy(() => import("../../../icons/BucketsIcon"));
const DashboardIcon = React.lazy(() => import("../../../icons/DashboardIcon"));
const DiagnosticsIcon = React.lazy(
() => import("../../../icons/DiagnosticsIcon")
);
const GroupsIcon = React.lazy(() => import("../../../icons/GroupsIcon"));
const IAMPoliciesIcon = React.lazy(
() => import("../../../icons/IAMPoliciesIcon")
@@ -61,7 +59,6 @@ const UsersIcon = React.lazy(() => import("../../../icons/UsersIcon"));
const VersionIcon = React.lazy(() => import("../../../icons/VersionIcon"));
const LicenseIcon = React.lazy(() => import("../../../icons/LicenseIcon"));
const HealIcon = React.lazy(() => import("../../../icons/HealIcon"));
const AccountIcon = React.lazy(() => import("../../../icons/AccountIcon"));
const DocumentationIcon = React.lazy(
() => import("../../../icons/DocumentationIcon")
@@ -290,6 +287,7 @@ interface IMenuProps {
distributedSetup: boolean;
sidebarOpen: boolean;
setMenuOpen: typeof setMenuOpen;
resetSession: typeof resetSession;
}
const Menu = ({
@@ -300,13 +298,14 @@ const Menu = ({
distributedSetup,
sidebarOpen,
setMenuOpen,
resetSession,
}: IMenuProps) => {
const logout = () => {
const deleteSession = () => {
clearSession();
userLoggedIn(false);
localStorage.setItem("userLoggedIn", "");
resetSession();
history.push("/login");
};
api
@@ -402,23 +401,6 @@ const Menu = ({
name: "Tools",
icon: ToolsIcon,
},
{
group: "Tools",
type: "item",
component: NavLink,
to: "/heal",
name: "Heal",
icon: HealIcon,
fsHidden: distributedSetup,
},
{
group: "Tools",
type: "item",
component: NavLink,
to: "/health-info",
name: "Diagnostic",
icon: DiagnosticsIcon,
},
{
group: "Operator",
type: "item",
@@ -438,6 +420,9 @@ const Menu = ({
];
const allowedPages = pages.reduce((result: any, item: any) => {
if (item.startsWith("/tools")) {
result["/tools"] = true;
}
result[item] = true;
return result;
}, {});
@@ -643,6 +628,10 @@ const mapState = (state: AppState) => ({
distributedSetup: state.system.distributedSetup,
});
const connector = connect(mapState, { userLoggedIn, setMenuOpen });
const connector = connect(mapState, {
userLoggedIn,
setMenuOpen,
resetSession,
});
export default connector(withStyles(styles)(Menu));

View File

@@ -20,7 +20,6 @@ import createStyles from "@mui/styles/createStyles";
import withStyles from "@mui/styles/withStyles";
import Grid from "@mui/material/Grid";
import { configurationElements } from "../utils";
import {
actionsTray,
containerForHeader,
@@ -29,6 +28,21 @@ import {
import PageHeader from "../../Common/PageHeader/PageHeader";
import SettingsCard from "../../Common/SettingsCard/SettingsCard";
import PageLayout from "../../Common/Layout/PageLayout";
import { IElement } from "../types";
import {
DiagnosticsIcon,
HealIcon,
LogsIcon,
SearchIcon,
TraceIcon,
WatchIcon,
} from "../../../../icons";
import { hasPermission } from "../../../../common/SecureComponent/SecureComponent";
import {
CONSOLE_UI_RESOURCE,
IAM_SCOPES,
} from "../../../../common/SecureComponent/permissions";
import SpeedtestIcon from "../../../../icons/SpeedtestIcon";
interface IConfigurationOptions {
classes: any;
@@ -76,6 +90,59 @@ const styles = (theme: Theme) =>
});
const ToolsList = ({ classes }: IConfigurationOptions) => {
const configurationElements: IElement[] = [
{
icon: <LogsIcon />,
configuration_id: "logs",
configuration_label: "Logs",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_CONSOLE_LOG_ACTION,
]),
},
{
icon: <SearchIcon />,
configuration_id: "audit-logs",
configuration_label: "Audit Logs",
},
{
icon: <WatchIcon />,
configuration_id: "watch",
configuration_label: "Watch",
},
{
icon: <TraceIcon />,
configuration_id: "trace",
configuration_label: "trace",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_TRACE_ACTION,
]),
},
{
icon: <HealIcon />,
configuration_id: "heal",
configuration_label: "heal",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_HEAL_ACTION,
]),
},
{
icon: <DiagnosticsIcon />,
configuration_id: "diagnostics",
configuration_label: "Diagnostics",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_HEALTH_ACTION,
]),
},
{
icon: <SpeedtestIcon />,
configuration_id: "speedtest",
configuration_label: "Speedtest",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_HEAL_ACTION,
]),
},
];
return (
<Fragment>
<PageHeader label={"Tools"} />

View File

@@ -1,75 +0,0 @@
// 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 from "react";
import { IElement } from "./types";
import {
DiagnosticsIcon,
HealIcon,
LogsIcon,
SearchIcon,
TraceIcon,
WatchIcon,
} from "../../../icons";
import SpeedtestIcon from "../../../icons/SpeedtestIcon";
import {
CONSOLE_UI_RESOURCE,
IAM_SCOPES,
} from "../../../common/SecureComponent/permissions";
import { hasPermission } from "../../../common/SecureComponent/SecureComponent";
export const configurationElements: IElement[] = [
{
icon: <LogsIcon />,
configuration_id: "logs",
configuration_label: "Logs",
},
{
icon: <SearchIcon />,
configuration_id: "audit-logs",
configuration_label: "Audit Logs",
},
{
icon: <WatchIcon />,
configuration_id: "watch",
configuration_label: "Watch",
},
{
icon: <TraceIcon />,
configuration_id: "trace",
configuration_label: "trace",
},
{
icon: <HealIcon />,
configuration_id: "heal",
configuration_label: "heal",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_HEAL_ACTION,
]),
},
{
icon: <DiagnosticsIcon />,
configuration_id: "diagnostics",
configuration_label: "Diagnostics",
},
{
icon: <SpeedtestIcon />,
configuration_id: "speedtest",
configuration_label: "Speedtest",
disabled: !hasPermission(CONSOLE_UI_RESOURCE, [
IAM_SCOPES.ADMIN_HEAL_ACTION,
]),
},
];

View File

@@ -17,12 +17,18 @@
import { ISessionResponse } from "./types";
export const SESSION_RESPONSE = "SESSION_RESPONSE";
export const RESET_SESSION = "RESET_SESSION";
interface SessionAction {
type: typeof SESSION_RESPONSE;
message: ISessionResponse;
}
export type SessionActionTypes = SessionAction;
interface ResetSessionAction {
type: typeof RESET_SESSION;
}
export type SessionActionTypes = SessionAction | ResetSessionAction;
export function saveSessionResponse(message: ISessionResponse) {
return {
@@ -30,3 +36,9 @@ export function saveSessionResponse(message: ISessionResponse) {
message: message,
};
}
export function resetSession() {
return {
type: RESET_SESSION,
};
}

View File

@@ -15,7 +15,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { ISessionResponse } from "./types";
import { SessionActionTypes, SESSION_RESPONSE } from "./actions";
import { RESET_SESSION, SESSION_RESPONSE, SessionActionTypes } from "./actions";
export interface ConsoleState {
session: ISessionResponse;
@@ -42,6 +42,11 @@ export function consoleReducer(
...state,
session: action.message,
};
case RESET_SESSION:
return {
...state,
session: initialState.session,
};
default:
return state;
}