mirror of
https://github.com/OpenMaxIO/openmaxio-object-browser
synced 2026-07-01 15:51:18 -07:00
Logs, Watch Slices to replace old reducers, Split Tenant Add slice (#2035)
Logs, Watch Slices to replace old reducers Signed-off-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
@@ -26,6 +26,7 @@ import { useDispatch, useSelector } from "react-redux";
|
||||
import {
|
||||
globalSetDistributedSetup,
|
||||
operatorMode,
|
||||
selOpMode,
|
||||
setSiteReplicationInfo,
|
||||
userLogged,
|
||||
} from "./systemSlice";
|
||||
@@ -40,9 +41,7 @@ interface ProtectedRouteProps {
|
||||
const ProtectedRoute = ({ Component }: ProtectedRouteProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const isOperatorMode = useSelector(
|
||||
(state: AppState) => state.system.operatorMode
|
||||
);
|
||||
const isOperatorMode = useSelector(selOpMode);
|
||||
|
||||
const [sessionLoading, setSessionLoading] = useState<boolean>(true);
|
||||
const userLoggedIn = useSelector((state: AppState) => state.system.loggedIn);
|
||||
|
||||
@@ -15,10 +15,9 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { connect, useDispatch } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import api from "../../../common/api";
|
||||
import { Box } from "@mui/material";
|
||||
@@ -55,14 +54,15 @@ import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton";
|
||||
import { selectSAs } from "../Configurations/utils";
|
||||
import DeleteMultipleServiceAccounts from "../Users/DeleteMultipleServiceAccounts";
|
||||
import ServiceAccountPolicy from "./ServiceAccountPolicy";
|
||||
import { AppState } from "../../../store";
|
||||
import { setErrorSnackMessage, setSnackBarMessage } from "../../../systemSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { selFeatures } from "../consoleSlice";
|
||||
|
||||
const DeleteServiceAccount = withSuspense(
|
||||
React.lazy(() => import("./DeleteServiceAccount"))
|
||||
);
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...actionsTray,
|
||||
...searchField,
|
||||
@@ -73,16 +73,18 @@ const styles = (theme: Theme) =>
|
||||
},
|
||||
...tableStyles,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
interface IServiceAccountsProps {
|
||||
classes: any;
|
||||
history: any;
|
||||
features: any;
|
||||
}
|
||||
|
||||
const Account = ({ classes, history, features }: IServiceAccountsProps) => {
|
||||
const Account = ({ history }: IServiceAccountsProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
const features = useSelector(selFeatures);
|
||||
|
||||
const [records, setRecords] = useState<string[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(false);
|
||||
const [filter, setFilter] = useState<string>("");
|
||||
@@ -302,10 +304,4 @@ const Account = ({ classes, history, features }: IServiceAccountsProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
features: state.console.session.features,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default withStyles(styles)(connector(Account));
|
||||
export default Account;
|
||||
|
||||
@@ -15,21 +15,18 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { connect, useDispatch } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Paper } from "@mui/material";
|
||||
import Tabs from "@mui/material/Tabs";
|
||||
import Tab from "@mui/material/Tab";
|
||||
import { AppState } from "../../../../store";
|
||||
|
||||
import { TabPanel } from "../../../shared/tabs";
|
||||
import { Policy } from "../../Policies/types";
|
||||
import { ISessionResponse } from "../../types";
|
||||
import { User } from "../../Users/types";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
|
||||
import api from "../../../../common/api";
|
||||
import history from "../../../../history";
|
||||
import { BucketInfo } from "../types";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
IAM_PAGES,
|
||||
@@ -43,17 +40,10 @@ import {
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import { tableStyles } from "../../Common/FormComponents/common/styleLibrary";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { encodeURLString } from "../../../../common/utils";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
session: state.console.session,
|
||||
loadingBucket: state.buckets.bucketDetails.loadingBucket,
|
||||
bucketInfo: state.buckets.bucketDetails.bucketInfo,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
|
||||
|
||||
function a11yProps(index: any) {
|
||||
return {
|
||||
@@ -63,25 +53,20 @@ function a11yProps(index: any) {
|
||||
}
|
||||
|
||||
interface IAccessDetailsProps {
|
||||
session: ISessionResponse;
|
||||
|
||||
classes: any;
|
||||
match: any;
|
||||
loadingBucket: boolean;
|
||||
bucketInfo: BucketInfo | null;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...tableStyles,
|
||||
});
|
||||
const AccessDetails = ({
|
||||
match,
|
||||
|
||||
loadingBucket,
|
||||
classes,
|
||||
}: IAccessDetailsProps) => {
|
||||
})
|
||||
);
|
||||
const AccessDetails = ({ match }: IAccessDetailsProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
|
||||
const [curTab, setCurTab] = useState<number>(0);
|
||||
const [loadingPolicies, setLoadingPolicies] = useState<boolean>(true);
|
||||
const [bucketPolicy, setBucketPolicy] = useState<Policy[]>([]);
|
||||
@@ -241,4 +226,4 @@ const AccessDetails = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(connector(AccessDetails));
|
||||
export default AccessDetails;
|
||||
|
||||
@@ -15,13 +15,10 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { connect, useDispatch } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Paper } from "@mui/material";
|
||||
import { AppState } from "../../../../store";
|
||||
import { ISessionResponse } from "../../types";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
|
||||
import api from "../../../../common/api";
|
||||
@@ -35,7 +32,6 @@ import {
|
||||
searchField,
|
||||
tableStyles,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { BucketInfo } from "../types";
|
||||
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
|
||||
import PanelTitle from "../../Common/PanelTitle/PanelTitle";
|
||||
import {
|
||||
@@ -46,6 +42,8 @@ import {
|
||||
import withSuspense from "../../Common/Components/withSuspense";
|
||||
import RBIconButton from "./SummaryItems/RBIconButton";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
|
||||
|
||||
const AddAccessRuleModal = withSuspense(
|
||||
React.lazy(() => import("./AddAccessRule"))
|
||||
@@ -57,7 +55,7 @@ const EditAccessRuleModal = withSuspense(
|
||||
React.lazy(() => import("./EditAccessRule"))
|
||||
);
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
"@global": {
|
||||
".rowLine:hover .iconFileElm": {
|
||||
@@ -72,31 +70,19 @@ const styles = (theme: Theme) =>
|
||||
...searchField,
|
||||
...objectBrowserCommon,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
session: state.console.session,
|
||||
loadingBucket: state.buckets.bucketDetails.loadingBucket,
|
||||
bucketInfo: state.buckets.bucketDetails.bucketInfo,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
})
|
||||
);
|
||||
|
||||
interface IAccessRuleProps {
|
||||
session: ISessionResponse;
|
||||
classes: any;
|
||||
match: any;
|
||||
loadingBucket: boolean;
|
||||
bucketInfo: BucketInfo | null;
|
||||
}
|
||||
|
||||
const AccessRule = ({
|
||||
classes,
|
||||
match,
|
||||
loadingBucket,
|
||||
bucketInfo,
|
||||
}: IAccessRuleProps) => {
|
||||
const AccessRule = ({ match }: IAccessRuleProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
|
||||
const [loadingAccessRules, setLoadingAccessRules] = useState<boolean>(true);
|
||||
const [accessRules, setAccessRules] = useState([]);
|
||||
const [addAccessRuleOpen, setAddAccessRuleOpen] = useState<boolean>(false);
|
||||
@@ -254,4 +240,4 @@ const AccessRule = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(connector(AccessRule));
|
||||
export default AccessRule;
|
||||
|
||||
@@ -51,9 +51,8 @@ import {
|
||||
import { LifecycleConfigIcon } from "../../../../icons";
|
||||
import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import { BucketVersioning } from "../types";
|
||||
import { AppState } from "../../../../store";
|
||||
import FormSwitchWrapper from "../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import { setModalErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { selDistSet, setModalErrorSnackMessage } from "../../../../systemSlice";
|
||||
|
||||
interface IReplicationModal {
|
||||
open: boolean;
|
||||
@@ -100,9 +99,7 @@ const AddLifecycleModal = ({
|
||||
bucketName,
|
||||
}: IReplicationModal) => {
|
||||
const dispatch = useDispatch();
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const [loadingTiers, setLoadingTiers] = useState<boolean>(true);
|
||||
const [tiersList, setTiersList] = useState<ITiersDropDown[]>([]);
|
||||
const [addLoading, setAddLoading] = useState(false);
|
||||
|
||||
@@ -30,8 +30,6 @@ import {
|
||||
pageContentStyles,
|
||||
searchField,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
import { AppState } from "../../../../store";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import PageHeader from "../../Common/PageHeader/PageHeader";
|
||||
|
||||
@@ -51,8 +49,17 @@ import {
|
||||
import withSuspense from "../../Common/Components/withSuspense";
|
||||
import RBIconButton from "./SummaryItems/RBIconButton";
|
||||
import { TrashIcon } from "../../../../icons";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { setBucketDetailsLoad, setBucketInfo } from "../bucketsSlice";
|
||||
import {
|
||||
selDistSet,
|
||||
selSiteRep,
|
||||
setErrorSnackMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import {
|
||||
selBucketDetailsInfo,
|
||||
selBucketDetailsLoading,
|
||||
setBucketDetailsLoad,
|
||||
setBucketInfo,
|
||||
} from "./bucketDetailsSlice";
|
||||
|
||||
const BucketsIcon = React.lazy(() => import("../../../../icons/BucketsIcon"));
|
||||
const FolderIcon = React.lazy(() => import("../../../../icons/FolderIcon"));
|
||||
@@ -107,18 +114,10 @@ interface IBucketDetailsProps {
|
||||
const BucketDetails = ({ classes, match, history }: IBucketDetailsProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const loadingBucket = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.loadingBucket
|
||||
);
|
||||
const bucketInfo = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.bucketInfo
|
||||
);
|
||||
const siteReplicationInfo = useSelector(
|
||||
(state: AppState) => state.system.siteReplicationInfo
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
const bucketInfo = useSelector(selBucketDetailsInfo);
|
||||
const siteReplicationInfo = useSelector(selSiteRep);
|
||||
|
||||
const [iniLoad, setIniLoad] = useState<boolean>(false);
|
||||
const [deleteOpen, setDeleteOpen] = useState<boolean>(false);
|
||||
|
||||
@@ -24,8 +24,6 @@ import Grid from "@mui/material/Grid";
|
||||
import AddIcon from "../../../../icons/AddIcon";
|
||||
import LambdaIcon from "../../../../icons/LambdaIcon";
|
||||
import { BucketEvent, BucketEventList } from "../types";
|
||||
|
||||
import { AppState } from "../../../../store";
|
||||
import {
|
||||
actionsTray,
|
||||
searchField,
|
||||
@@ -45,6 +43,7 @@ import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
|
||||
import withSuspense from "../../Common/Components/withSuspense";
|
||||
import RBIconButton from "./SummaryItems/RBIconButton";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
|
||||
|
||||
const DeleteEvent = withSuspense(React.lazy(() => import("./DeleteEvent")));
|
||||
const AddEvent = withSuspense(React.lazy(() => import("./AddEvent")));
|
||||
@@ -66,9 +65,7 @@ interface IBucketEventsProps {
|
||||
const BucketEventsPanel = ({ classes, match }: IBucketEventsProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const loadingBucket = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.loadingBucket
|
||||
);
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
|
||||
const [addEventScreenOpen, setAddEventScreenOpen] = useState<boolean>(false);
|
||||
const [loadingEvents, setLoadingEvents] = useState<boolean>(true);
|
||||
|
||||
@@ -27,8 +27,6 @@ import {
|
||||
actionsTray,
|
||||
searchField,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
import { AppState } from "../../../../store";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import api from "../../../../common/api";
|
||||
import EditLifecycleConfiguration from "./EditLifecycleConfiguration";
|
||||
@@ -43,6 +41,7 @@ import {
|
||||
import { IAM_SCOPES } from "../../../../common/SecureComponent/permissions";
|
||||
import RBIconButton from "./SummaryItems/RBIconButton";
|
||||
import DeleteBucketLifecycleRule from "./DeleteBucketLifecycleRule";
|
||||
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -62,9 +61,7 @@ const BucketLifecyclePanel = ({
|
||||
classes,
|
||||
match,
|
||||
}: IBucketLifecyclePanelProps) => {
|
||||
const loadingBucket = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.loadingBucket
|
||||
);
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
|
||||
const [loadingLifecycle, setLoadingLifecycle] = useState<boolean>(true);
|
||||
const [lifecycleRecords, setLifecycleRecords] = useState<LifeCycleItem[]>([]);
|
||||
|
||||
@@ -31,7 +31,6 @@ import {
|
||||
BucketReplicationRule,
|
||||
} from "../types";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import { AppState } from "../../../../store";
|
||||
import {
|
||||
hasPermission,
|
||||
SecureComponent,
|
||||
@@ -46,6 +45,7 @@ import withSuspense from "../../Common/Components/withSuspense";
|
||||
import RBIconButton from "./SummaryItems/RBIconButton";
|
||||
import EditReplicationModal from "./EditReplicationModal";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { selBucketDetailsLoading } from "./bucketDetailsSlice";
|
||||
|
||||
const AddReplicationModal = withSuspense(
|
||||
React.lazy(() => import("./AddReplicationModal"))
|
||||
@@ -74,9 +74,7 @@ const BucketReplicationPanel = ({
|
||||
}: IBucketReplicationProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const loadingBucket = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.loadingBucket
|
||||
);
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
|
||||
const [loadingReplication, setLoadingReplication] = useState<boolean>(true);
|
||||
const [replicationRules, setReplicationRules] = useState<
|
||||
|
||||
@@ -21,7 +21,6 @@ import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Box, Grid } from "@mui/material";
|
||||
import get from "lodash/get";
|
||||
import { AppState } from "../../../../store";
|
||||
import {
|
||||
BucketEncryptionInfo,
|
||||
BucketObjectLocking,
|
||||
@@ -54,8 +53,12 @@ import EditablePropertyItem from "./SummaryItems/EditablePropertyItem";
|
||||
import ReportedUsage from "./SummaryItems/ReportedUsage";
|
||||
import BucketQuotaSize from "./SummaryItems/BucketQuotaSize";
|
||||
import SectionTitle from "../../Common/SectionTitle";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { setBucketDetailsLoad } from "../bucketsSlice";
|
||||
import { selDistSet, setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import {
|
||||
selBucketDetailsInfo,
|
||||
selBucketDetailsLoading,
|
||||
setBucketDetailsLoad,
|
||||
} from "./bucketDetailsSlice";
|
||||
|
||||
const SetAccessPolicy = withSuspense(
|
||||
React.lazy(() => import("./SetAccessPolicy"))
|
||||
@@ -96,16 +99,10 @@ interface IBucketSummaryProps {
|
||||
const BucketSummary = ({ classes, match }: IBucketSummaryProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const loadingBucket = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.loadingBucket
|
||||
);
|
||||
const bucketInfo = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.bucketInfo
|
||||
);
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
const bucketInfo = useSelector(selBucketDetailsInfo);
|
||||
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
|
||||
const [encryptionCfg, setEncryptionCfg] =
|
||||
useState<BucketEncryptionInfo | null>(null);
|
||||
|
||||
@@ -24,21 +24,13 @@ import {
|
||||
modalStyleUtils,
|
||||
spacingUtils,
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { connect, useDispatch } from "react-redux";
|
||||
import { useDispatch } from "react-redux";
|
||||
import api from "../../../../common/api";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
|
||||
import { AppState } from "../../../../store";
|
||||
import SelectWrapper from "../../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import { AddAccessRuleIcon } from "../../../../icons";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
session: state.console.session,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
interface IEditAccessRule {
|
||||
classes: any;
|
||||
modalOpen: boolean;
|
||||
@@ -136,4 +128,4 @@ const EditAccessRule = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(connector(EditAccessRule));
|
||||
export default withStyles(styles)(EditAccessRule);
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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 { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { BucketInfo } from "../types";
|
||||
import { AppState } from "../../../../store";
|
||||
|
||||
export interface BucketDetailsState {
|
||||
selectedTab: string;
|
||||
loadingBucket: boolean;
|
||||
bucketInfo: BucketInfo | null;
|
||||
}
|
||||
|
||||
const initialState: BucketDetailsState = {
|
||||
selectedTab: "summary",
|
||||
loadingBucket: false,
|
||||
bucketInfo: null,
|
||||
};
|
||||
|
||||
export const bucketDetailsSlice = createSlice({
|
||||
name: "trace",
|
||||
initialState,
|
||||
reducers: {
|
||||
setBucketDetailsTab: (state, action: PayloadAction<string>) => {
|
||||
state.selectedTab = action.payload;
|
||||
},
|
||||
setBucketDetailsLoad: (state, action: PayloadAction<boolean>) => {
|
||||
state.loadingBucket = action.payload;
|
||||
},
|
||||
setBucketInfo: (state, action: PayloadAction<BucketInfo | null>) => {
|
||||
state.bucketInfo = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setBucketDetailsTab, setBucketInfo, setBucketDetailsLoad } =
|
||||
bucketDetailsSlice.actions;
|
||||
|
||||
export const selBucketDetailsLoading = (state: AppState) =>
|
||||
state.bucketDetails.loadingBucket;
|
||||
export const selBucketDetailsInfo = (state: AppState) =>
|
||||
state.bucketDetails.bucketInfo;
|
||||
|
||||
export default bucketDetailsSlice.reducer;
|
||||
@@ -41,7 +41,11 @@ import InputUnitMenu from "../../Common/FormComponents/InputUnitMenu/InputUnitMe
|
||||
import FormLayout from "../../Common/FormLayout";
|
||||
import HelpBox from "../../../../common/HelpBox";
|
||||
import SectionTitle from "../../Common/SectionTitle";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import {
|
||||
selDistSet,
|
||||
selSiteRep,
|
||||
setErrorSnackMessage,
|
||||
} from "../../../../systemSlice";
|
||||
import {
|
||||
addBucketEnableObjectLocking,
|
||||
addBucketName,
|
||||
@@ -141,12 +145,8 @@ const AddBucket = ({ classes }: IAddBucketProps) => {
|
||||
const retentionValidity = useSelector(
|
||||
(state: AppState) => state.buckets.addBucketRetentionValidity
|
||||
);
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const siteReplicationInfo = useSelector(
|
||||
(state: AppState) => state.system.siteReplicationInfo
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const siteReplicationInfo = useSelector(selSiteRep);
|
||||
|
||||
const [addLoading, setAddLoading] = useState<boolean>(false);
|
||||
const [sendEnabled, setSendEnabled] = useState<boolean>(false);
|
||||
|
||||
@@ -95,7 +95,7 @@ import {
|
||||
setErrorSnackMessage,
|
||||
setSnackBarMessage,
|
||||
} from "../../../../../../systemSlice";
|
||||
import { setBucketDetailsLoad, setBucketInfo } from "../../../bucketsSlice";
|
||||
|
||||
import {
|
||||
makeid,
|
||||
storeCallForObjectWithID,
|
||||
@@ -119,6 +119,12 @@ import {
|
||||
updateProgress,
|
||||
} from "../../../../ObjectBrowser/objectBrowserSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import {
|
||||
selBucketDetailsInfo,
|
||||
selBucketDetailsLoading,
|
||||
setBucketDetailsLoad,
|
||||
setBucketInfo,
|
||||
} from "../../../BucketDetails/bucketDetailsSlice";
|
||||
|
||||
const HistoryIcon = React.lazy(
|
||||
() => import("../../../../../../icons/HistoryIcon")
|
||||
@@ -303,12 +309,8 @@ const ListObjects = ({ match, history }: IListObjectsProps) => {
|
||||
(state: AppState) => state.objectBrowser.simplePath
|
||||
);
|
||||
|
||||
const loadingBucket = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.loadingBucket
|
||||
);
|
||||
const bucketInfo = useSelector(
|
||||
(state: AppState) => state.buckets.bucketDetails.bucketInfo
|
||||
);
|
||||
const loadingBucket = useSelector(selBucketDetailsLoading);
|
||||
const bucketInfo = useSelector(selBucketDetailsInfo);
|
||||
const allowResources = useSelector(
|
||||
(state: AppState) => state.console.session.allowResources
|
||||
);
|
||||
@@ -921,14 +923,14 @@ const ListObjects = ({ match, history }: IListObjectsProps) => {
|
||||
errorMessage = "something went wrong";
|
||||
}
|
||||
}
|
||||
dispatch(dispatch(failObject(identity)));
|
||||
dispatch(failObject(identity));
|
||||
reject({ status: xhr.status, message: errorMessage });
|
||||
}
|
||||
};
|
||||
|
||||
xhr.upload.addEventListener("error", (event) => {
|
||||
reject(errorMessage);
|
||||
dispatch(dispatch(failObject(identity)));
|
||||
dispatch(failObject(identity));
|
||||
return;
|
||||
});
|
||||
|
||||
@@ -1014,7 +1016,6 @@ const ListObjects = ({ match, history }: IListObjectsProps) => {
|
||||
[bucketName, dispatch, simplePath]
|
||||
);
|
||||
|
||||
|
||||
const onDrop = useCallback(
|
||||
(acceptedFiles: any[]) => {
|
||||
if (acceptedFiles && acceptedFiles.length > 0) {
|
||||
|
||||
@@ -71,6 +71,7 @@ import { displayFileIconName } from "./utils";
|
||||
import TagsModal from "../ObjectDetails/TagsModal";
|
||||
import InspectObject from "./InspectObject";
|
||||
import Loader from "../../../../Common/Loader/Loader";
|
||||
import { selDistSet } from "../../../../../../systemSlice";
|
||||
import {
|
||||
makeid,
|
||||
storeCallForObjectWithID,
|
||||
@@ -159,9 +160,7 @@ const ObjectDetailPanel = ({
|
||||
}: IObjectDetailPanelProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const versionsMode = useSelector(
|
||||
(state: AppState) => state.objectBrowser.versionsMode
|
||||
);
|
||||
|
||||
@@ -29,7 +29,6 @@ import {
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
import { IFileInfo } from "./types";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { ErrorResponseHandler } from "../../../../../../common/types";
|
||||
import api from "../../../../../../common/api";
|
||||
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
|
||||
@@ -39,6 +38,7 @@ import { encodeURLString } from "../../../../../../common/utils";
|
||||
import { ShareIcon } from "../../../../../../icons";
|
||||
import BoxIconButton from "../../../../Common/BoxIconButton/BoxIconButton";
|
||||
import {
|
||||
selDistSet,
|
||||
setModalErrorSnackMessage,
|
||||
setModalSnackMessage,
|
||||
} from "../../../../../../systemSlice";
|
||||
@@ -95,9 +95,7 @@ const ShareFile = ({
|
||||
dataObject,
|
||||
}: IShareFileProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const [shareURL, setShareURL] = useState<string>("");
|
||||
const [isLoadingVersion, setIsLoadingVersion] = useState<boolean>(true);
|
||||
const [isLoadingFile, setIsLoadingFile] = useState<boolean>(false);
|
||||
|
||||
@@ -21,8 +21,6 @@ import { Box, Button, Grid } from "@mui/material";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { ErrorResponseHandler } from "../../../../../../common/types";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import ModalWrapper from "../../../../Common/ModalWrapper/ModalWrapper";
|
||||
@@ -43,7 +41,10 @@ import { IAM_SCOPES } from "../../../../../../common/SecureComponent/permissions
|
||||
import { SecureComponent } from "../../../../../../common/SecureComponent";
|
||||
import Chip from "@mui/material/Chip";
|
||||
import CloseIcon from "@mui/icons-material/Close";
|
||||
import { setModalErrorSnackMessage } from "../../../../../../systemSlice";
|
||||
import {
|
||||
selDistSet,
|
||||
setModalErrorSnackMessage,
|
||||
} from "../../../../../../systemSlice";
|
||||
|
||||
interface ITagModal {
|
||||
modalOpen: boolean;
|
||||
@@ -99,9 +100,7 @@ const AddTagModal = ({
|
||||
classes,
|
||||
}: ITagModal) => {
|
||||
const dispatch = useDispatch();
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const [newKey, setNewKey] = useState<string>("");
|
||||
const [newLabel, setNewLabel] = useState<string>("");
|
||||
const [isSending, setIsSending] = useState<boolean>(false);
|
||||
|
||||
@@ -61,7 +61,10 @@ import RBIconButton from "../../../BucketDetails/SummaryItems/RBIconButton";
|
||||
import DeleteNonCurrent from "../ListObjects/DeleteNonCurrent";
|
||||
import BrowserBreadcrumbs from "../../../../ObjectBrowser/BrowserBreadcrumbs";
|
||||
import DeleteSelectedVersions from "./DeleteSelectedVersions";
|
||||
import { setErrorSnackMessage } from "../../../../../../systemSlice";
|
||||
import {
|
||||
selDistSet,
|
||||
setErrorSnackMessage,
|
||||
} from "../../../../../../systemSlice";
|
||||
import {
|
||||
makeid,
|
||||
storeCallForObjectWithID,
|
||||
@@ -171,9 +174,7 @@ const VersionsNavigator = ({
|
||||
(state: AppState) => state.objectBrowser.selectedVersion
|
||||
);
|
||||
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const [shareFileModalOpen, setShareFileModalOpen] = useState<boolean>(false);
|
||||
const [actualInfo, setActualInfo] = useState<IFileInfo | null>(null);
|
||||
const [objectToShare, setObjectToShare] = useState<IFileInfo | null>(null);
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { BucketInfo } from "./types";
|
||||
|
||||
export interface BucketsState {
|
||||
open: boolean;
|
||||
@@ -30,13 +29,6 @@ export interface BucketsState {
|
||||
addBucketRetentionMode: string;
|
||||
addBucketRetentionUnit: string;
|
||||
addBucketRetentionValidity: number;
|
||||
bucketDetails: BucketDetailsState;
|
||||
}
|
||||
|
||||
export interface BucketDetailsState {
|
||||
selectedTab: string;
|
||||
loadingBucket: boolean;
|
||||
bucketInfo: BucketInfo | null;
|
||||
}
|
||||
|
||||
const initialState: BucketsState = {
|
||||
@@ -52,11 +44,6 @@ const initialState: BucketsState = {
|
||||
addBucketRetentionMode: "compliance",
|
||||
addBucketRetentionUnit: "days",
|
||||
addBucketRetentionValidity: 180,
|
||||
bucketDetails: {
|
||||
selectedTab: "summary",
|
||||
loadingBucket: false,
|
||||
bucketInfo: null,
|
||||
},
|
||||
};
|
||||
|
||||
export const bucketsSlice = createSlice({
|
||||
@@ -99,9 +86,7 @@ export const bucketsSlice = createSlice({
|
||||
addBucketRetentionValidity: (state, action: PayloadAction<number>) => {
|
||||
state.addBucketRetentionValidity = action.payload;
|
||||
},
|
||||
setBucketDetailsTab: (state, action: PayloadAction<string>) => {
|
||||
state.bucketDetails.selectedTab = action.payload;
|
||||
},
|
||||
|
||||
addBucketReset: (state) => {
|
||||
state.addBucketName = "";
|
||||
state.addBucketVersioningEnabled = false;
|
||||
@@ -115,12 +100,6 @@ export const bucketsSlice = createSlice({
|
||||
state.addBucketRetentionUnit = "days";
|
||||
state.addBucketRetentionValidity = 180;
|
||||
},
|
||||
setBucketDetailsLoad: (state, action: PayloadAction<boolean>) => {
|
||||
state.bucketDetails.loadingBucket = action.payload;
|
||||
},
|
||||
setBucketInfo: (state, action: PayloadAction<BucketInfo | null>) => {
|
||||
state.bucketDetails.bucketInfo = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -138,9 +117,6 @@ export const {
|
||||
addBucketRetentionMode,
|
||||
addBucketRetentionUnit,
|
||||
addBucketRetentionValidity,
|
||||
setBucketDetailsTab,
|
||||
setBucketDetailsLoad,
|
||||
setBucketInfo,
|
||||
} = bucketsSlice.actions;
|
||||
|
||||
export default bucketsSlice.reducer;
|
||||
|
||||
@@ -34,10 +34,11 @@ import makeStyles from "@mui/styles/makeStyles";
|
||||
import { routesAsKbarActions } from "./kbar-actions";
|
||||
import { Box } from "@mui/material";
|
||||
import { MenuExpandedIcon } from "../../icons/SidebarMenus";
|
||||
import { AppState } from "../../store";
|
||||
import { connect } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import useApi from "./Common/Hooks/useApi";
|
||||
import { Bucket, BucketList } from "./Buckets/types";
|
||||
import { selFeatures } from "./consoleSlice";
|
||||
import { selOpMode } from "../../systemSlice";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
resultItem: {
|
||||
@@ -124,13 +125,10 @@ const KBarStateChangeMonitor = ({
|
||||
return null;
|
||||
};
|
||||
|
||||
const CommandBar = ({
|
||||
features = [],
|
||||
operatorMode = false,
|
||||
}: {
|
||||
operatorMode?: boolean;
|
||||
features?: string[] | null;
|
||||
}) => {
|
||||
const CommandBar = () => {
|
||||
const operatorMode = useSelector(selOpMode);
|
||||
const features = useSelector(selFeatures);
|
||||
|
||||
const [buckets, setBuckets] = useState<Bucket[]>([]);
|
||||
|
||||
const [, invokeListBucketsApi] = useApi(
|
||||
@@ -319,11 +317,4 @@ const ResultItem = React.forwardRef(
|
||||
}
|
||||
);
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
operatorMode: state.system.operatorMode,
|
||||
features: state.console.session.features,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default connector(CommandBar);
|
||||
export default CommandBar;
|
||||
|
||||
@@ -28,6 +28,8 @@ import ConsoleLogo from "../../../../icons/ConsoleLogo";
|
||||
import { CircleIcon, ObjectManagerIcon } from "../../../../icons";
|
||||
import { Box } from "@mui/material";
|
||||
import { toggleList } from "../../ObjectBrowser/objectBrowserSlice";
|
||||
import { selFeatures } from "../../consoleSlice";
|
||||
import { selOpMode } from "../../../../systemSlice";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -104,15 +106,11 @@ const PageHeader = ({
|
||||
const sidebarOpen = useSelector(
|
||||
(state: AppState) => state.system.sidebarOpen
|
||||
);
|
||||
const operatorMode = useSelector(
|
||||
(state: AppState) => state.system.operatorMode
|
||||
);
|
||||
const operatorMode = useSelector(selOpMode);
|
||||
const managerObjects = useSelector(
|
||||
(state: AppState) => state.objectBrowser.objectManager.objectsToManage
|
||||
);
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
const managerOpen = useSelector(
|
||||
(state: AppState) => state.objectBrowser.objectManager.managerOpen
|
||||
);
|
||||
|
||||
@@ -45,7 +45,6 @@ import PageLayout from "../../Common/Layout/PageLayout";
|
||||
import SearchBox from "../../Common/SearchBox";
|
||||
|
||||
import withSuspense from "../../Common/Components/withSuspense";
|
||||
import { AppState } from "../../../../store";
|
||||
import DistributedOnly from "../../Common/DistributedOnly/DistributedOnly";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
@@ -55,7 +54,7 @@ import {
|
||||
import { SecureComponent } from "../../../../common/SecureComponent";
|
||||
import { tierTypes } from "./utils";
|
||||
import RBIconButton from "../../Buckets/BucketDetails/SummaryItems/RBIconButton";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { selDistSet, setErrorSnackMessage } from "../../../../systemSlice";
|
||||
|
||||
const UpdateTierCredentialsModal = withSuspense(
|
||||
React.lazy(() => import("./UpdateTierCredentialsModal"))
|
||||
@@ -96,9 +95,7 @@ const styles = (theme: Theme) =>
|
||||
|
||||
const ListTiersConfiguration = ({ classes, history }: IListTiersConfig) => {
|
||||
const dispatch = useDispatch();
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const [records, setRecords] = useState<ITierElement[]>([]);
|
||||
const [filter, setFilter] = useState<string>("");
|
||||
const [isLoading, setIsLoading] = useState<boolean>(true);
|
||||
|
||||
@@ -53,10 +53,13 @@ import EditPool from "./Tenants/TenantDetails/Pools/EditPool/EditPool";
|
||||
import ComponentsScreen from "./Common/ComponentsScreen";
|
||||
import {
|
||||
menuOpen,
|
||||
selDistSet,
|
||||
selOpMode,
|
||||
serverIsLoading,
|
||||
setServerNeedsRestart,
|
||||
setSnackBarMessage,
|
||||
} from "../../systemSlice";
|
||||
import { selFeatures, selSession } from "./consoleSlice";
|
||||
|
||||
const Trace = React.lazy(() => import("./Trace/Trace"));
|
||||
const Heal = React.lazy(() => import("./Heal/Heal"));
|
||||
@@ -181,16 +184,10 @@ interface IConsoleProps {
|
||||
const Console = ({ classes }: IConsoleProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const open = useSelector((state: AppState) => state.system.sidebarOpen);
|
||||
const session = useSelector((state: AppState) => state.console.session);
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
);
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const operatorMode = useSelector(
|
||||
(state: AppState) => state.system.operatorMode
|
||||
);
|
||||
const session = useSelector(selSession);
|
||||
const features = useSelector(selFeatures);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const operatorMode = useSelector(selOpMode);
|
||||
const snackBarMessage = useSelector(
|
||||
(state: AppState) => state.system.snackBar
|
||||
);
|
||||
|
||||
@@ -16,14 +16,12 @@
|
||||
import * as React from "react";
|
||||
import { KBarProvider } from "kbar";
|
||||
import Console from "./Console";
|
||||
import { AppState } from "../../store";
|
||||
import { useSelector } from "react-redux";
|
||||
import CommandBar from "./CommandBar";
|
||||
import { selFeatures } from "./consoleSlice";
|
||||
|
||||
const ConsoleKBar = () => {
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
// if we are hiding the menu also disable the k-bar so just return console
|
||||
if (features?.includes("hide-menu")) {
|
||||
return <Console />;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import { HorizontalBar } from "react-chartjs-2";
|
||||
import {
|
||||
Button,
|
||||
@@ -44,7 +44,6 @@ import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
IAM_SCOPES,
|
||||
} from "../../../common/SecureComponent/permissions";
|
||||
import { AppState } from "../../../store";
|
||||
import { ErrorResponseHandler } from "../../../common/types";
|
||||
import { HealIcon } from "../../../icons";
|
||||
import CheckboxWrapper from "../Common/FormComponents/CheckboxWrapper/CheckboxWrapper";
|
||||
@@ -53,8 +52,10 @@ import api from "../../../common/api";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import { SecureComponent } from "../../../common/SecureComponent";
|
||||
import DistributedOnly from "../Common/DistributedOnly/DistributedOnly";
|
||||
import { selDistSet } from "../../../systemSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
graphContainer: {
|
||||
backgroundColor: "#fff",
|
||||
@@ -96,12 +97,8 @@ const styles = (theme: Theme) =>
|
||||
...inlineCheckboxes,
|
||||
...searchField,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
|
||||
interface IHeal {
|
||||
classes: any;
|
||||
distributedSetup: boolean;
|
||||
}
|
||||
})
|
||||
);
|
||||
|
||||
const SelectStyled = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -118,7 +115,10 @@ const SelectStyled = withStyles((theme: Theme) =>
|
||||
})
|
||||
)(InputBase);
|
||||
|
||||
const Heal = ({ classes, distributedSetup }: IHeal) => {
|
||||
const Heal = () => {
|
||||
const classes = useStyles();
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
|
||||
const [start, setStart] = useState(false);
|
||||
const [bucketName, setBucketName] = useState("");
|
||||
const [bucketList, setBucketList] = useState<Bucket[]>([]);
|
||||
@@ -389,10 +389,4 @@ const Heal = ({ classes, distributedSetup }: IHeal) => {
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
distributedSetup: state.system.distributedSetup,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default connector(withStyles(styles)(Heal));
|
||||
export default Heal;
|
||||
|
||||
@@ -15,17 +15,15 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Box, LinearProgress } from "@mui/material";
|
||||
import clsx from "clsx";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Button from "@mui/material/Button";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { SubnetInfo } from "./types";
|
||||
import { AppState } from "../../../store";
|
||||
import { containerForHeader } from "../Common/FormComponents/common/styleLibrary";
|
||||
import PageHeader from "../Common/PageHeader/PageHeader";
|
||||
import LicenseModal from "./LicenseModal";
|
||||
@@ -46,14 +44,10 @@ import LicensePlans from "./LicensePlans";
|
||||
import { Link } from "react-router-dom";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import RegistrationStatusBanner from "../Support/RegistrationStatusBanner";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { selOpMode } from "../../../systemSlice";
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
operatorMode: state.system.operatorMode,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
pageTitle: {
|
||||
backgroundColor: "rgb(250,250,252)",
|
||||
@@ -120,14 +114,12 @@ const styles = (theme: Theme) =>
|
||||
marginRight: 15,
|
||||
},
|
||||
},
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
interface ILicenseProps {
|
||||
classes: any;
|
||||
operatorMode: boolean;
|
||||
}
|
||||
|
||||
const License = ({ classes, operatorMode }: ILicenseProps) => {
|
||||
const License = () => {
|
||||
const classes = useStyles();
|
||||
const operatorMode = useSelector(selOpMode);
|
||||
const [activateProductModal, setActivateProductModal] =
|
||||
useState<boolean>(false);
|
||||
|
||||
@@ -454,4 +446,4 @@ const License = ({ classes, operatorMode }: ILicenseProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default connector(withStyles(styles)(License));
|
||||
export default License;
|
||||
|
||||
@@ -18,7 +18,7 @@ import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { connect } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import {
|
||||
Button,
|
||||
FormControl,
|
||||
@@ -32,11 +32,7 @@ import moment from "moment/moment";
|
||||
import { ErrorResponseHandler } from "../../../../../src/common/types";
|
||||
import api from "../../../../../src/common/api";
|
||||
import { AppState } from "../../../../store";
|
||||
import {
|
||||
logMessageReceived,
|
||||
logResetMessages,
|
||||
setLogsStarted,
|
||||
} from "../actions";
|
||||
|
||||
import { LogMessage } from "../types";
|
||||
import { wsProtocol } from "../../../../utils/wsUtils";
|
||||
import {
|
||||
@@ -54,8 +50,14 @@ import Table from "@mui/material/Table";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import TableContainer from "@mui/material/TableContainer";
|
||||
import LogLine from "./LogLine";
|
||||
import {
|
||||
logMessageReceived,
|
||||
logResetMessages,
|
||||
setLogsStarted,
|
||||
} from "../logsSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
logList: {
|
||||
background: "#fff",
|
||||
@@ -86,7 +88,8 @@ const styles = (theme: Theme) =>
|
||||
...logsCommon,
|
||||
...inlineCheckboxes,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const SelectStyled = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -102,25 +105,15 @@ const SelectStyled = withStyles((theme: Theme) =>
|
||||
})
|
||||
)(InputBase);
|
||||
|
||||
interface ILogs {
|
||||
classes: any;
|
||||
logMessageReceived: typeof logMessageReceived;
|
||||
logResetMessages: typeof logResetMessages;
|
||||
setLogsStarted: typeof setLogsStarted;
|
||||
messages: LogMessage[];
|
||||
logsStarted: boolean;
|
||||
}
|
||||
|
||||
var c: any = null;
|
||||
|
||||
const ErrorLogs = ({
|
||||
classes,
|
||||
logMessageReceived,
|
||||
logResetMessages,
|
||||
setLogsStarted,
|
||||
messages,
|
||||
logsStarted,
|
||||
}: ILogs) => {
|
||||
const ErrorLogs = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const messages = useSelector((state: AppState) => state.logs.logMessages);
|
||||
const logsStarted = useSelector((state: AppState) => state.logs.logsStarted);
|
||||
|
||||
const [filter, setFilter] = useState<string>("");
|
||||
const [nodes, setNodes] = useState<string[]>([""]);
|
||||
const [selectedNode, setSelectedNode] = useState<string>("all");
|
||||
@@ -131,7 +124,7 @@ const ErrorLogs = ({
|
||||
const [loadingNodes, setLoadingNodes] = useState<boolean>(false);
|
||||
|
||||
const startLogs = () => {
|
||||
logResetMessages();
|
||||
dispatch(logResetMessages());
|
||||
const url = new URL(window.location.toString());
|
||||
const isDev = process.env.NODE_ENV === "development";
|
||||
const port = isDev ? "9090" : url.port;
|
||||
@@ -152,7 +145,7 @@ const ErrorLogs = ({
|
||||
if (c !== null) {
|
||||
c.onopen = () => {
|
||||
console.log("WebSocket Client Connected");
|
||||
setLogsStarted(true);
|
||||
dispatch(setLogsStarted(true));
|
||||
c.send("ok");
|
||||
interval = setInterval(() => {
|
||||
c.send("ok");
|
||||
@@ -169,18 +162,18 @@ const ErrorLogs = ({
|
||||
userAgents.push(m.userAgent);
|
||||
setUserAgents(userAgents);
|
||||
}
|
||||
logMessageReceived(m);
|
||||
dispatch(logMessageReceived(m));
|
||||
};
|
||||
c.onclose = () => {
|
||||
clearInterval(interval);
|
||||
console.log("connection closed by server");
|
||||
setLogsStarted(false);
|
||||
dispatch(setLogsStarted(false));
|
||||
};
|
||||
return () => {
|
||||
c.close(1000);
|
||||
clearInterval(interval);
|
||||
console.log("closing websockets");
|
||||
setLogsStarted(false);
|
||||
dispatch(setLogsStarted(false));
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -188,7 +181,7 @@ const ErrorLogs = ({
|
||||
const stopLogs = () => {
|
||||
if (c !== null && c !== undefined) {
|
||||
c.close(1000);
|
||||
setLogsStarted(false);
|
||||
dispatch(setLogsStarted(false));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -397,16 +390,5 @@ const ErrorLogs = ({
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
messages: state.logs.logMessages,
|
||||
logsStarted: state.logs.logsStarted,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
logMessageReceived: logMessageReceived,
|
||||
logResetMessages: logResetMessages,
|
||||
setLogsStarted,
|
||||
});
|
||||
|
||||
//export default withStyles(styles)(connector(ErrorLogs));
|
||||
export default connector(withStyles(styles)(ErrorLogs));
|
||||
export default ErrorLogs;
|
||||
|
||||
@@ -29,8 +29,6 @@ import {
|
||||
} from "../../Common/FormComponents/common/styleLibrary";
|
||||
import { IReqInfoSearchResults, ISearchResponse } from "./types";
|
||||
import { niceBytes, nsToSeconds } from "../../../../common/utils";
|
||||
|
||||
import { AppState } from "../../../../store";
|
||||
import { ErrorResponseHandler } from "../../../../common/types";
|
||||
import api from "../../../../common/api";
|
||||
import TableWrapper from "../../Common/TableWrapper/TableWrapper";
|
||||
@@ -49,6 +47,7 @@ import { SecureComponent } from "../../../../common/SecureComponent";
|
||||
import { SearchIcon } from "../../../../icons";
|
||||
import MissingIntegration from "../../Common/MissingIntegration/MissingIntegration";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { selFeatures } from "../../consoleSlice";
|
||||
|
||||
interface ILogSearchProps {
|
||||
classes: any;
|
||||
@@ -122,9 +121,7 @@ const styles = (theme: Theme) =>
|
||||
|
||||
const LogsSearchMain = ({ classes }: ILogSearchProps) => {
|
||||
const dispatch = useDispatch();
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [timeStart, setTimeStart] = useState<any>(null);
|
||||
|
||||
@@ -1,60 +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 { LogMessage } from "./types";
|
||||
|
||||
export const LOG_MESSAGE_RECEIVED = "LOG_MESSAGE_RECEIVED";
|
||||
export const LOG_RESET_MESSAGES = "LOG_RESET_MESSAGES";
|
||||
export const LOG_SET_STARTED = "LOG_SET_STARTED";
|
||||
|
||||
interface LogMessageReceivedAction {
|
||||
type: typeof LOG_MESSAGE_RECEIVED;
|
||||
message: LogMessage;
|
||||
}
|
||||
|
||||
interface LogResetMessagesAction {
|
||||
type: typeof LOG_RESET_MESSAGES;
|
||||
}
|
||||
|
||||
interface LogSetStarted {
|
||||
type: typeof LOG_SET_STARTED;
|
||||
status: boolean;
|
||||
}
|
||||
|
||||
export type LogActionTypes =
|
||||
| LogMessageReceivedAction
|
||||
| LogResetMessagesAction
|
||||
| LogSetStarted;
|
||||
|
||||
export function logMessageReceived(message: LogMessage) {
|
||||
return {
|
||||
type: LOG_MESSAGE_RECEIVED,
|
||||
message: message,
|
||||
};
|
||||
}
|
||||
|
||||
export function logResetMessages() {
|
||||
return {
|
||||
type: LOG_RESET_MESSAGES,
|
||||
};
|
||||
}
|
||||
|
||||
export function setLogsStarted(status: boolean) {
|
||||
return {
|
||||
type: LOG_SET_STARTED,
|
||||
status,
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
// Copyright (c) 2022 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
|
||||
@@ -14,12 +14,7 @@
|
||||
// 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 {
|
||||
LOG_MESSAGE_RECEIVED,
|
||||
LOG_RESET_MESSAGES,
|
||||
LOG_SET_STARTED,
|
||||
LogActionTypes,
|
||||
} from "./actions";
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { LogMessage } from "./types";
|
||||
|
||||
export interface LogState {
|
||||
@@ -32,47 +27,40 @@ const initialState: LogState = {
|
||||
logsStarted: false,
|
||||
};
|
||||
|
||||
export function logReducer(
|
||||
state = initialState,
|
||||
action: LogActionTypes
|
||||
): LogState {
|
||||
switch (action.type) {
|
||||
case LOG_MESSAGE_RECEIVED:
|
||||
// if it's a simple ConsoleMsg, append it to the current ConsoleMsg in the
|
||||
// state if any
|
||||
let msgs = [...state.logMessages];
|
||||
export const logsSlice = createSlice({
|
||||
name: "logs",
|
||||
initialState,
|
||||
reducers: {
|
||||
logMessageReceived: (state, action: PayloadAction<LogMessage>) => {
|
||||
let msgs = state.logMessages;
|
||||
|
||||
if (
|
||||
msgs.length > 0 &&
|
||||
action.message.time.getFullYear() === 1 &&
|
||||
action.message.ConsoleMsg !== ""
|
||||
action.payload.time.getFullYear() === 1 &&
|
||||
action.payload.ConsoleMsg !== ""
|
||||
) {
|
||||
for (let m in msgs) {
|
||||
if (msgs[m].time.getFullYear() === 1) {
|
||||
msgs[
|
||||
m
|
||||
].ConsoleMsg = `${msgs[m].ConsoleMsg}\n${action.message.ConsoleMsg}`;
|
||||
].ConsoleMsg = `${msgs[m].ConsoleMsg}\n${action.payload.ConsoleMsg}`;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
msgs.push(action.message);
|
||||
msgs.push(action.payload);
|
||||
}
|
||||
state.logMessages = msgs;
|
||||
},
|
||||
logResetMessages: (state) => {
|
||||
state.logMessages = [];
|
||||
},
|
||||
setLogsStarted: (state, action: PayloadAction<boolean>) => {
|
||||
state.logsStarted = action.payload;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
...state,
|
||||
logMessages: msgs,
|
||||
};
|
||||
case LOG_RESET_MESSAGES:
|
||||
return {
|
||||
...state,
|
||||
logMessages: [],
|
||||
};
|
||||
case LOG_SET_STARTED:
|
||||
return {
|
||||
...state,
|
||||
logsStarted: action.status,
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export const { logMessageReceived, logResetMessages, setLogsStarted } =
|
||||
logsSlice.actions;
|
||||
|
||||
export default logsSlice.reducer;
|
||||
@@ -32,8 +32,8 @@ import api from "../../../common/api";
|
||||
import MenuToggle from "./MenuToggle";
|
||||
import ConsoleMenuList from "./ConsoleMenuList";
|
||||
import { validRoutes } from "../valid-routes";
|
||||
import { menuOpen, userLogged } from "../../../systemSlice";
|
||||
import { resetSession } from "../consoleSlice";
|
||||
import { menuOpen, selOpMode, userLogged } from "../../../systemSlice";
|
||||
import { resetSession, selFeatures } from "../consoleSlice";
|
||||
|
||||
const drawerWidth = 250;
|
||||
|
||||
@@ -91,16 +91,12 @@ interface IMenuProps {
|
||||
const Menu = ({ classes }: IMenuProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
|
||||
const sidebarOpen = useSelector(
|
||||
(state: AppState) => state.system.sidebarOpen
|
||||
);
|
||||
const operatorMode = useSelector(
|
||||
(state: AppState) => state.system.operatorMode
|
||||
);
|
||||
const operatorMode = useSelector(selOpMode);
|
||||
|
||||
const logout = () => {
|
||||
const deleteSession = () => {
|
||||
|
||||
@@ -56,11 +56,11 @@ import {
|
||||
} from "../../../common/SecureComponent";
|
||||
|
||||
import withSuspense from "../Common/Components/withSuspense";
|
||||
import { AppState } from "../../../store";
|
||||
import RBIconButton from "../Buckets/BucketDetails/SummaryItems/RBIconButton";
|
||||
import PolicyView from "./PolicyView";
|
||||
import { decodeURLString, encodeURLString } from "../../../common/utils";
|
||||
import { setErrorSnackMessage, setSnackBarMessage } from "../../../systemSlice";
|
||||
import { selFeatures } from "../consoleSlice";
|
||||
|
||||
const DeletePolicy = withSuspense(React.lazy(() => import("./DeletePolicy")));
|
||||
|
||||
@@ -100,9 +100,7 @@ interface IPolicyDetailsProps {
|
||||
const PolicyDetails = ({ classes, match }: IPolicyDetailsProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
|
||||
const [policy, setPolicy] = useState<Policy | null>(null);
|
||||
const [policyStatements, setPolicyStatements] = useState<IAMStatement[]>([]);
|
||||
|
||||
@@ -15,12 +15,11 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { Fragment, useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket";
|
||||
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 moment from "moment/moment";
|
||||
import PageHeader from "../Common/PageHeader/PageHeader";
|
||||
import {
|
||||
@@ -32,7 +31,6 @@ import {
|
||||
} from "../Common/FormComponents/common/styleLibrary";
|
||||
import { wsProtocol } from "../../../utils/wsUtils";
|
||||
import { SpeedTestResponse } from "./types";
|
||||
import { AppState } from "../../../store";
|
||||
import { SpeedtestIcon } from "../../../icons";
|
||||
import {
|
||||
CONSOLE_UI_RESOURCE,
|
||||
@@ -48,13 +46,10 @@ import DistributedOnly from "../Common/DistributedOnly/DistributedOnly";
|
||||
import HelpBox from "../../../common/HelpBox";
|
||||
import WarnIcon from "../../../icons/WarnIcon";
|
||||
import Loader from "../Common/Loader/Loader";
|
||||
import { selDistSet } from "../../../systemSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
interface ISpeedtest {
|
||||
classes: any;
|
||||
distributedSetup: boolean;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
advancedContent: {
|
||||
backgroundColor: "#FBFAFA",
|
||||
@@ -79,9 +74,12 @@ const styles = (theme: Theme) =>
|
||||
...searchField,
|
||||
...formFieldStyles,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const Speedtest = ({ classes, distributedSetup }: ISpeedtest) => {
|
||||
const Speedtest = () => {
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const classes = useStyles();
|
||||
const [start, setStart] = useState<boolean>(false);
|
||||
|
||||
const [currStatus, setCurrStatus] = useState<SpeedTestResponse[] | null>(
|
||||
@@ -311,10 +309,4 @@ const Speedtest = ({ classes, distributedSetup }: ISpeedtest) => {
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
distributedSetup: state.system.distributedSetup,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default connector(withStyles(styles)(Speedtest));
|
||||
export default Speedtest;
|
||||
|
||||
@@ -58,12 +58,11 @@ import { useDispatch, useSelector } from "react-redux";
|
||||
|
||||
import SettingsIcon from "../../../icons/SettingsIcon";
|
||||
import FormSwitchWrapper from "../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import { AppState } from "../../../store";
|
||||
|
||||
import RegisterHelpBox from "./RegisterHelpBox";
|
||||
import RegistrationStatusBanner from "./RegistrationStatusBanner";
|
||||
import BackLink from "../../../common/BackLink";
|
||||
import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import { selOpMode, setErrorSnackMessage } from "../../../systemSlice";
|
||||
|
||||
interface IRegister {
|
||||
classes: any;
|
||||
@@ -153,9 +152,7 @@ const FormTitle = ({ icon = null, title }: { icon?: any; title: any }) => {
|
||||
|
||||
const Register = ({ classes }: IRegister) => {
|
||||
const dispatch = useDispatch();
|
||||
const operatorMode = useSelector(
|
||||
(state: AppState) => state.system.operatorMode
|
||||
);
|
||||
const operatorMode = useSelector(selOpMode);
|
||||
const [license, setLicense] = useState<string>("");
|
||||
const [subnetPassword, setSubnetPassword] = useState<string>("");
|
||||
const [subnetEmail, setSubnetEmail] = useState<string>("");
|
||||
|
||||
@@ -22,7 +22,6 @@ import { LinearProgress } from "@mui/material";
|
||||
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import {
|
||||
modalBasic,
|
||||
settingsCommon,
|
||||
@@ -59,13 +58,11 @@ import {
|
||||
import HelpBox from "../../../../common/HelpBox";
|
||||
import { StorageIcon } from "../../../../icons";
|
||||
import { setErrorSnackMessage } from "../../../../systemSlice";
|
||||
import { resetAddTenantForm } from "../tenantsSlice";
|
||||
import { selFeatures } from "../../consoleSlice";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { resetAddTenantForm } from "./createTenantSlice";
|
||||
|
||||
interface IAddTenantProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
pageBox: {
|
||||
border: "1px solid #EAEAEA",
|
||||
@@ -73,32 +70,30 @@ const styles = (theme: Theme) =>
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
...settingsCommon,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const AddTenant = ({ classes }: IAddTenantProps) => {
|
||||
const AddTenant = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const namespace = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.nameTenant.namespace
|
||||
(state: AppState) => state.createTenant.fields.nameTenant.namespace
|
||||
);
|
||||
const validPages = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.validPages
|
||||
);
|
||||
const fields = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields
|
||||
(state: AppState) => state.createTenant.validPages
|
||||
);
|
||||
const fields = useSelector((state: AppState) => state.createTenant.fields);
|
||||
const certificates = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.certificates
|
||||
(state: AppState) => state.createTenant.certificates
|
||||
);
|
||||
const selectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
state.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
const tolerations = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.tolerations
|
||||
(state: AppState) => state.createTenant.tolerations
|
||||
);
|
||||
|
||||
// Modals
|
||||
@@ -874,4 +869,4 @@ const AddTenant = ({ classes }: IAddTenantProps) => {
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(AddTenant);
|
||||
export default AddTenant;
|
||||
|
||||
@@ -48,7 +48,7 @@ import {
|
||||
setKeyValuePairs,
|
||||
setTolerationInfo,
|
||||
updateAddField,
|
||||
} from "../../tenantsSlice";
|
||||
} from "../createTenantSlice";
|
||||
|
||||
interface IAffinityProps {
|
||||
classes: any;
|
||||
@@ -119,21 +119,19 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const podAffinity = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.affinity.podAffinity
|
||||
(state: AppState) => state.createTenant.fields.affinity.podAffinity
|
||||
);
|
||||
const nodeSelectorLabels = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.affinity.nodeSelectorLabels
|
||||
(state: AppState) => state.createTenant.fields.affinity.nodeSelectorLabels
|
||||
);
|
||||
const withPodAntiAffinity = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.affinity.withPodAntiAffinity
|
||||
(state: AppState) => state.createTenant.fields.affinity.withPodAntiAffinity
|
||||
);
|
||||
const keyValuePairs = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.nodeSelectorPairs
|
||||
(state: AppState) => state.createTenant.nodeSelectorPairs
|
||||
);
|
||||
const tolerations = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.tolerations
|
||||
(state: AppState) => state.createTenant.tolerations
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
@@ -325,13 +323,12 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
<SelectWrapper
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
const newKey = e.target.value as string;
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
|
||||
arrCp[i].key = e.target.value as string;
|
||||
arrCp[i].value = keyValueMap[newKey][0];
|
||||
const newLKP: LabelKeyPair = {
|
||||
key: newKey,
|
||||
value: keyValueMap[newKey][0],
|
||||
};
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = newLKP;
|
||||
dispatch(setKeyValuePairs(arrCp));
|
||||
}}
|
||||
id="select-access-policy"
|
||||
@@ -348,11 +345,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
name={`nodeselector-${i.toString()}`}
|
||||
value={kvp.key}
|
||||
onChange={(e) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].key = e.target.value;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setKeyValuePairs(arrCp));
|
||||
}}
|
||||
index={i}
|
||||
@@ -364,11 +361,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
{keyOptions.length > 0 && (
|
||||
<SelectWrapper
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].value = e.target.value as string;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setKeyValuePairs(arrCp));
|
||||
}}
|
||||
id="select-access-policy"
|
||||
@@ -391,11 +388,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
name={`nodeselector-${i.toString()}`}
|
||||
value={kvp.value}
|
||||
onChange={(e) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].value = e.target.value;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setKeyValuePairs(arrCp));
|
||||
}}
|
||||
index={i}
|
||||
@@ -408,7 +405,7 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
const arrCp = Object.assign([], keyValuePairs);
|
||||
const arrCp = [...keyValuePairs];
|
||||
if (keyOptions.length > 0) {
|
||||
arrCp.push({
|
||||
key: keyOptions[0].value,
|
||||
|
||||
@@ -36,7 +36,7 @@ import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/Inpu
|
||||
import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import InputUnitMenu from "../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import SectionH1 from "../../../Common/SectionH1";
|
||||
import { isPageValid, updateAddField } from "../../tenantsSlice";
|
||||
import { isPageValid, updateAddField } from "../createTenantSlice";
|
||||
|
||||
interface IConfigureProps {
|
||||
classes: any;
|
||||
@@ -85,48 +85,44 @@ const ConfigLogSearch = ({ classes }: IConfigureProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const storageClasses = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.storageClasses
|
||||
(state: AppState) => state.createTenant.storageClasses
|
||||
);
|
||||
const logSearchEnabled = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchEnabled
|
||||
(state: AppState) => state.createTenant.fields.configure.logSearchEnabled
|
||||
);
|
||||
const logSearchVolumeSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchVolumeSize
|
||||
(state: AppState) => state.createTenant.fields.configure.logSearchVolumeSize
|
||||
);
|
||||
const logSearchSelectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchSelectedStorageClass
|
||||
state.createTenant.fields.configure.logSearchSelectedStorageClass
|
||||
);
|
||||
const logSearchImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchImage
|
||||
(state: AppState) => state.createTenant.fields.configure.logSearchImage
|
||||
);
|
||||
const logSearchPostgresImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchPostgresImage
|
||||
state.createTenant.fields.configure.logSearchPostgresImage
|
||||
);
|
||||
const logSearchPostgresInitImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchPostgresInitImage
|
||||
state.createTenant.fields.configure.logSearchPostgresInitImage
|
||||
);
|
||||
const selectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass
|
||||
state.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const tenantSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.tenantSecurityContext
|
||||
state.createTenant.fields.configure.tenantSecurityContext
|
||||
);
|
||||
const logSearchSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchSecurityContext
|
||||
state.createTenant.fields.configure.logSearchSecurityContext
|
||||
);
|
||||
const logSearchPostgresSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure
|
||||
.logSearchPostgresSecurityContext
|
||||
state.createTenant.fields.configure.logSearchPostgresSecurityContext
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
@@ -37,7 +37,7 @@ import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/Inpu
|
||||
import SelectWrapper from "../../../Common/FormComponents/SelectWrapper/SelectWrapper";
|
||||
import InputUnitMenu from "../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import SectionH1 from "../../../Common/SectionH1";
|
||||
import { isPageValid, updateAddField } from "../../tenantsSlice";
|
||||
import { isPageValid, updateAddField } from "../createTenantSlice";
|
||||
|
||||
interface IConfigureProps {
|
||||
classes: any;
|
||||
@@ -85,43 +85,40 @@ const ConfigPrometheus = ({ classes }: IConfigureProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const storageClasses = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.storageClasses
|
||||
(state: AppState) => state.createTenant.storageClasses
|
||||
);
|
||||
const prometheusEnabled = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusEnabled
|
||||
(state: AppState) => state.createTenant.fields.configure.prometheusEnabled
|
||||
);
|
||||
const prometheusVolumeSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusVolumeSize
|
||||
state.createTenant.fields.configure.prometheusVolumeSize
|
||||
);
|
||||
const prometheusSelectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusSelectedStorageClass
|
||||
state.createTenant.fields.configure.prometheusSelectedStorageClass
|
||||
);
|
||||
const prometheusImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusImage
|
||||
(state: AppState) => state.createTenant.fields.configure.prometheusImage
|
||||
);
|
||||
const prometheusSidecarImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusSidecarImage
|
||||
state.createTenant.fields.configure.prometheusSidecarImage
|
||||
);
|
||||
const prometheusInitImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusInitImage
|
||||
(state: AppState) => state.createTenant.fields.configure.prometheusInitImage
|
||||
);
|
||||
const selectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass
|
||||
state.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const tenantSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.tenantSecurityContext
|
||||
state.createTenant.fields.configure.tenantSecurityContext
|
||||
);
|
||||
const prometheusSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusSecurityContext
|
||||
state.createTenant.fields.configure.prometheusSecurityContext
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
@@ -41,7 +41,7 @@ import {
|
||||
isPageValid,
|
||||
removeMinIODomain,
|
||||
updateAddField,
|
||||
} from "../../tenantsSlice";
|
||||
} from "../createTenantSlice";
|
||||
|
||||
interface IConfigureProps {
|
||||
classes: any;
|
||||
@@ -105,30 +105,26 @@ const Configure = ({ classes }: IConfigureProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const exposeMinIO = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.configure.exposeMinIO
|
||||
(state: AppState) => state.createTenant.fields.configure.exposeMinIO
|
||||
);
|
||||
const exposeConsole = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.exposeConsole
|
||||
(state: AppState) => state.createTenant.fields.configure.exposeConsole
|
||||
);
|
||||
const setDomains = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.configure.setDomains
|
||||
(state: AppState) => state.createTenant.fields.configure.setDomains
|
||||
);
|
||||
const consoleDomain = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.consoleDomain
|
||||
(state: AppState) => state.createTenant.fields.configure.consoleDomain
|
||||
);
|
||||
const minioDomains = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.minioDomains
|
||||
(state: AppState) => state.createTenant.fields.configure.minioDomains
|
||||
);
|
||||
const tenantCustom = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.tenantCustom
|
||||
(state: AppState) => state.createTenant.fields.configure.tenantCustom
|
||||
);
|
||||
const tenantSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.tenantSecurityContext
|
||||
state.createTenant.fields.configure.tenantSecurityContext
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
@@ -41,13 +41,15 @@ import {
|
||||
import SectionH1 from "../../../Common/SectionH1";
|
||||
import {
|
||||
addFileClientCert,
|
||||
addFileGemaltoCa,
|
||||
addFileServerCert,
|
||||
addFileVaultCa,
|
||||
addFileVaultCert,
|
||||
isPageValid,
|
||||
updateAddField,
|
||||
} from "../../tenantsSlice";
|
||||
} from "../createTenantSlice";
|
||||
import VaultKMSAdd from "./Encryption/VaultKMSAdd";
|
||||
import AzureKMSAdd from "./Encryption/AzureKMSAdd";
|
||||
import GCPKMSAdd from "./Encryption/GCPKMSAdd";
|
||||
import GemaltoKMSAdd from "./Encryption/GemaltoKMSAdd";
|
||||
import AWSKMSAdd from "./Encryption/AWSKMSAdd";
|
||||
|
||||
interface IEncryptionProps {
|
||||
classes: any;
|
||||
@@ -83,166 +85,58 @@ const Encryption = ({ classes }: IEncryptionProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const replicas = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.replicas
|
||||
(state: AppState) => state.createTenant.fields.encryption.replicas
|
||||
);
|
||||
const enableEncryption = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.enableEncryption
|
||||
(state: AppState) => state.createTenant.fields.encryption.enableEncryption
|
||||
);
|
||||
const encryptionType = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.encryptionType
|
||||
);
|
||||
const gemaltoEndpoint = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gemaltoEndpoint
|
||||
);
|
||||
const gemaltoToken = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gemaltoToken
|
||||
);
|
||||
const gemaltoDomain = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gemaltoDomain
|
||||
);
|
||||
const gemaltoRetry = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gemaltoRetry
|
||||
);
|
||||
const awsEndpoint = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.awsEndpoint
|
||||
);
|
||||
const awsRegion = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.awsRegion
|
||||
);
|
||||
const awsKMSKey = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.awsKMSKey
|
||||
);
|
||||
const awsAccessKey = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.awsAccessKey
|
||||
);
|
||||
const awsSecretKey = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.awsSecretKey
|
||||
);
|
||||
const awsToken = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.awsToken
|
||||
);
|
||||
const vaultEndpoint = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.vaultEndpoint
|
||||
);
|
||||
const vaultEngine = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.vaultEngine
|
||||
);
|
||||
const vaultNamespace = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.vaultNamespace
|
||||
);
|
||||
const vaultPrefix = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.vaultPrefix
|
||||
);
|
||||
const vaultAppRoleEngine = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.vaultAppRoleEngine
|
||||
);
|
||||
const vaultId = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.vaultId
|
||||
);
|
||||
const vaultSecret = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.vaultSecret
|
||||
);
|
||||
const vaultRetry = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.vaultRetry
|
||||
);
|
||||
const vaultPing = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.encryption.vaultPing
|
||||
);
|
||||
const azureEndpoint = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.azureEndpoint
|
||||
);
|
||||
const azureTenantID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.azureTenantID
|
||||
);
|
||||
const azureClientID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.azureClientID
|
||||
);
|
||||
const azureClientSecret = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.azureClientSecret
|
||||
(state: AppState) => state.createTenant.fields.encryption.encryptionType
|
||||
);
|
||||
|
||||
const gcpProjectID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gcpProjectID
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpProjectID
|
||||
);
|
||||
const gcpEndpoint = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gcpEndpoint
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpEndpoint
|
||||
);
|
||||
const gcpClientEmail = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gcpClientEmail
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpClientEmail
|
||||
);
|
||||
const gcpClientID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gcpClientID
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpClientID
|
||||
);
|
||||
const gcpPrivateKeyID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gcpPrivateKeyID
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpPrivateKeyID
|
||||
);
|
||||
const gcpPrivateKey = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.gcpPrivateKey
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpPrivateKey
|
||||
);
|
||||
const enableCustomCertsForKES = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.enableCustomCertsForKES
|
||||
state.createTenant.fields.encryption.enableCustomCertsForKES
|
||||
);
|
||||
const enableAutoCert = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.security.enableAutoCert
|
||||
(state: AppState) => state.createTenant.fields.security.enableAutoCert
|
||||
);
|
||||
const enableTLS = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.security.enableTLS
|
||||
(state: AppState) => state.createTenant.fields.security.enableTLS
|
||||
);
|
||||
const minioCertificates = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.certificates.minioCertificates
|
||||
(state: AppState) => state.createTenant.certificates.minioCertificates
|
||||
);
|
||||
const serverCertificate = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.certificates.serverCertificate
|
||||
(state: AppState) => state.createTenant.certificates.serverCertificate
|
||||
);
|
||||
const clientCertificate = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.certificates.clientCertificate
|
||||
);
|
||||
const vaultCertificate = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.certificates.vaultCertificate
|
||||
);
|
||||
const vaultCA = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.certificates.vaultCA
|
||||
);
|
||||
const gemaltoCA = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.certificates.gemaltoCA
|
||||
(state: AppState) => state.createTenant.certificates.clientCertificate
|
||||
);
|
||||
|
||||
const enableCustomCerts = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.security.enableCustomCerts
|
||||
(state: AppState) => state.createTenant.fields.security.enableCustomCerts
|
||||
);
|
||||
const kesSecurityContext = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.encryption.kesSecurityContext
|
||||
(state: AppState) => state.createTenant.fields.encryption.kesSecurityContext
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
@@ -341,121 +235,6 @@ const Encryption = ({ classes }: IEncryptionProps) => {
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (encryptionType === "vault") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "vault_endpoint",
|
||||
required: true,
|
||||
value: vaultEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_id",
|
||||
required: true,
|
||||
value: vaultId,
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_secret",
|
||||
required: true,
|
||||
value: vaultSecret,
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_ping",
|
||||
required: false,
|
||||
value: vaultPing,
|
||||
customValidation: parseInt(vaultPing) < 0,
|
||||
customValidationMessage: "Value needs to be 0 or greater",
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_retry",
|
||||
required: false,
|
||||
value: vaultRetry,
|
||||
customValidation: parseInt(vaultRetry) < 0,
|
||||
customValidationMessage: "Value needs to be 0 or greater",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (encryptionType === "aws") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "aws_endpoint",
|
||||
required: true,
|
||||
value: awsEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "aws_region",
|
||||
required: true,
|
||||
value: awsRegion,
|
||||
},
|
||||
{
|
||||
fieldKey: "aws_accessKey",
|
||||
required: true,
|
||||
value: awsAccessKey,
|
||||
},
|
||||
{
|
||||
fieldKey: "aws_secretKey",
|
||||
required: true,
|
||||
value: awsSecretKey,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (encryptionType === "gemalto") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "gemalto_endpoint",
|
||||
required: true,
|
||||
value: gemaltoEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "gemalto_token",
|
||||
required: true,
|
||||
value: gemaltoToken,
|
||||
},
|
||||
{
|
||||
fieldKey: "gemalto_domain",
|
||||
required: true,
|
||||
value: gemaltoDomain,
|
||||
},
|
||||
{
|
||||
fieldKey: "gemalto_retry",
|
||||
required: false,
|
||||
value: gemaltoRetry,
|
||||
customValidation: parseInt(gemaltoRetry) < 0,
|
||||
customValidationMessage: "Value needs to be 0 or greater",
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (encryptionType === "azure") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "azure_endpoint",
|
||||
required: true,
|
||||
value: azureEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "azure_tenant_id",
|
||||
required: true,
|
||||
value: azureTenantID,
|
||||
},
|
||||
{
|
||||
fieldKey: "azure_client_id",
|
||||
required: true,
|
||||
value: azureClientID,
|
||||
},
|
||||
{
|
||||
fieldKey: "azure_client_secret",
|
||||
required: true,
|
||||
value: azureClientSecret,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(encryptionValidation);
|
||||
@@ -471,30 +250,12 @@ const Encryption = ({ classes }: IEncryptionProps) => {
|
||||
}, [
|
||||
enableEncryption,
|
||||
encryptionType,
|
||||
vaultEndpoint,
|
||||
vaultEngine,
|
||||
vaultId,
|
||||
vaultSecret,
|
||||
vaultPing,
|
||||
vaultRetry,
|
||||
awsEndpoint,
|
||||
awsRegion,
|
||||
awsSecretKey,
|
||||
awsAccessKey,
|
||||
gemaltoEndpoint,
|
||||
gemaltoToken,
|
||||
gemaltoDomain,
|
||||
gemaltoRetry,
|
||||
gcpProjectID,
|
||||
gcpEndpoint,
|
||||
gcpClientEmail,
|
||||
gcpClientID,
|
||||
gcpPrivateKeyID,
|
||||
gcpPrivateKey,
|
||||
azureEndpoint,
|
||||
azureTenantID,
|
||||
azureClientID,
|
||||
azureClientSecret,
|
||||
dispatch,
|
||||
enableAutoCert,
|
||||
enableCustomCerts,
|
||||
@@ -565,534 +326,11 @@ const Encryption = ({ classes }: IEncryptionProps) => {
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
{encryptionType === "vault" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_endpoint"
|
||||
name="vault_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultEndpoint", e.target.value);
|
||||
cleanValidation("vault_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={vaultEndpoint}
|
||||
error={validationErrors["vault_endpoint"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_engine"
|
||||
name="vault_engine"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultEngine", e.target.value);
|
||||
cleanValidation("vault_engine");
|
||||
}}
|
||||
label="Engine"
|
||||
value={vaultEngine}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_namespace"
|
||||
name="vault_namespace"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultNamespace", e.target.value);
|
||||
}}
|
||||
label="Namespace"
|
||||
value={vaultNamespace}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_prefix"
|
||||
name="vault_prefix"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultPrefix", e.target.value);
|
||||
}}
|
||||
label="Prefix"
|
||||
value={vaultPrefix}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
App Role
|
||||
</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_approle_engine"
|
||||
name="vault_approle_engine"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultAppRoleEngine", e.target.value);
|
||||
}}
|
||||
label="Engine"
|
||||
value={vaultAppRoleEngine}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_id"
|
||||
name="vault_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultId", e.target.value);
|
||||
cleanValidation("vault_id");
|
||||
}}
|
||||
label="AppRole ID"
|
||||
value={vaultId}
|
||||
error={validationErrors["vault_id"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_secret"
|
||||
name="vault_secret"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultSecret", e.target.value);
|
||||
cleanValidation("vault_secret");
|
||||
}}
|
||||
label="AppRole Secret"
|
||||
value={vaultSecret}
|
||||
error={validationErrors["vault_secret"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id="vault_retry"
|
||||
name="vault_retry"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultRetry", e.target.value);
|
||||
cleanValidation("vault_retry");
|
||||
}}
|
||||
label="Retry (Seconds)"
|
||||
value={vaultRetry}
|
||||
error={validationErrors["vault_retry"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
|
||||
<Grid container className={classes.mutualTlsConfig}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Mutual TLS authentication (optional)
|
||||
</legend>
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileVaultCert({
|
||||
key: "key",
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("vault_key");
|
||||
}}
|
||||
accept=".key,.pem"
|
||||
id="vault_key"
|
||||
name="vault_key"
|
||||
label="Key"
|
||||
value={vaultCertificate.key}
|
||||
/>
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileVaultCert({
|
||||
key: "cert",
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("vault_cert");
|
||||
}}
|
||||
accept=".cer,.crt,.cert,.pem"
|
||||
id="vault_cert"
|
||||
name="vault_cert"
|
||||
label="Cert"
|
||||
value={vaultCertificate.cert}
|
||||
/>
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileVaultCa({
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("vault_ca");
|
||||
}}
|
||||
accept=".cer,.crt,.cert,.pem"
|
||||
id="vault_ca"
|
||||
name="vault_ca"
|
||||
label="CA"
|
||||
value={vaultCA.cert}
|
||||
/>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
className={classes.formFieldRow}
|
||||
style={{ marginTop: 15 }}
|
||||
>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>Status</legend>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id="vault_ping"
|
||||
name="vault_ping"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultPing", e.target.value);
|
||||
cleanValidation("vault_ping");
|
||||
}}
|
||||
label="Ping (Seconds)"
|
||||
value={vaultPing}
|
||||
error={validationErrors["vault_ping"] || ""}
|
||||
/>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
{encryptionType === "azure" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_endpoint"
|
||||
name="azure_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureEndpoint", e.target.value);
|
||||
cleanValidation("azure_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={azureEndpoint}
|
||||
error={validationErrors["azure_endpoint"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Credentials
|
||||
</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_tenant_id"
|
||||
name="azure_tenant_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureTenantID", e.target.value);
|
||||
cleanValidation("azure_tenant_id");
|
||||
}}
|
||||
label="Tenant ID"
|
||||
value={azureTenantID}
|
||||
error={validationErrors["azure_tenant_id"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_client_id"
|
||||
name="azure_client_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureClientID", e.target.value);
|
||||
cleanValidation("azure_client_id");
|
||||
}}
|
||||
label="Client ID"
|
||||
value={azureClientID}
|
||||
error={validationErrors["azure_client_id"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_client_secret"
|
||||
name="azure_client_secret"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureClientSecret", e.target.value);
|
||||
cleanValidation("azure_client_secret");
|
||||
}}
|
||||
label="Client Secret"
|
||||
value={azureClientSecret}
|
||||
error={validationErrors["azure_client_secret"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
{encryptionType === "gcp" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_project_id"
|
||||
name="gcp_project_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpProjectID", e.target.value);
|
||||
}}
|
||||
label="Project ID"
|
||||
value={gcpProjectID}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_endpoint"
|
||||
name="gcp_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpEndpoint", e.target.value);
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={gcpEndpoint}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Credentials
|
||||
</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_client_email"
|
||||
name="gcp_client_email"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpClientEmail", e.target.value);
|
||||
}}
|
||||
label="Client Email"
|
||||
value={gcpClientEmail}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_client_id"
|
||||
name="gcp_client_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpClientID", e.target.value);
|
||||
}}
|
||||
label="Client ID"
|
||||
value={gcpClientID}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_private_key_id"
|
||||
name="gcp_private_key_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpPrivateKeyID", e.target.value);
|
||||
}}
|
||||
label="Private Key ID"
|
||||
value={gcpPrivateKeyID}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_private_key"
|
||||
name="gcp_private_key"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpPrivateKey", e.target.value);
|
||||
}}
|
||||
label="Private Key"
|
||||
value={gcpPrivateKey}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
{encryptionType === "aws" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_endpoint"
|
||||
name="aws_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsEndpoint", e.target.value);
|
||||
cleanValidation("aws_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={awsEndpoint}
|
||||
error={validationErrors["aws_endpoint"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_region"
|
||||
name="aws_region"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsRegion", e.target.value);
|
||||
cleanValidation("aws_region");
|
||||
}}
|
||||
label="Region"
|
||||
value={awsRegion}
|
||||
error={validationErrors["aws_region"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_kmsKey"
|
||||
name="aws_kmsKey"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsKMSKey", e.target.value);
|
||||
}}
|
||||
label="KMS Key"
|
||||
value={awsKMSKey}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Credentials
|
||||
</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_accessKey"
|
||||
name="aws_accessKey"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsAccessKey", e.target.value);
|
||||
cleanValidation("aws_accessKey");
|
||||
}}
|
||||
label="Access Key"
|
||||
value={awsAccessKey}
|
||||
error={validationErrors["aws_accessKey"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_secretKey"
|
||||
name="aws_secretKey"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsSecretKey", e.target.value);
|
||||
cleanValidation("aws_secretKey");
|
||||
}}
|
||||
label="Secret Key"
|
||||
value={awsSecretKey}
|
||||
error={validationErrors["aws_secretKey"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_token"
|
||||
name="aws_token"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsToken", e.target.value);
|
||||
}}
|
||||
label="Token"
|
||||
value={awsToken}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
{encryptionType === "gemalto" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gemalto_endpoint"
|
||||
name="gemalto_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoEndpoint", e.target.value);
|
||||
cleanValidation("gemalto_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={gemaltoEndpoint}
|
||||
error={validationErrors["gemalto_endpoint"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
style={{
|
||||
marginBottom: 15,
|
||||
}}
|
||||
>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Credentials
|
||||
</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gemalto_token"
|
||||
name="gemalto_token"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoToken", e.target.value);
|
||||
cleanValidation("gemalto_token");
|
||||
}}
|
||||
label="Token"
|
||||
value={gemaltoToken}
|
||||
error={validationErrors["gemalto_token"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gemalto_domain"
|
||||
name="gemalto_domain"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoDomain", e.target.value);
|
||||
cleanValidation("gemalto_domain");
|
||||
}}
|
||||
label="Domain"
|
||||
value={gemaltoDomain}
|
||||
error={validationErrors["gemalto_domain"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id="gemalto_retry"
|
||||
name="gemalto_retry"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoRetry", e.target.value);
|
||||
cleanValidation("gemalto_retry");
|
||||
}}
|
||||
label="Retry (seconds)"
|
||||
value={gemaltoRetry}
|
||||
error={validationErrors["gemalto_retry"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
style={{
|
||||
marginBottom: 15,
|
||||
}}
|
||||
>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Custom CA Root certificate verification
|
||||
</legend>
|
||||
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileGemaltoCa({
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("gemalto_ca");
|
||||
}}
|
||||
accept=".cer,.crt,.cert,.pem"
|
||||
id="gemalto_ca"
|
||||
name="gemalto_ca"
|
||||
label="CA"
|
||||
value={gemaltoCA.cert}
|
||||
/>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
{encryptionType === "vault" && <VaultKMSAdd />}
|
||||
{encryptionType === "azure" && <AzureKMSAdd />}
|
||||
{encryptionType === "gcp" && <GCPKMSAdd />}
|
||||
{encryptionType === "aws" && <AWSKMSAdd />}
|
||||
{encryptionType === "gemalto" && <GemaltoKMSAdd />}
|
||||
<div className={classes.headerElement}>
|
||||
<h4 className={classes.h3Section}>Additional Configurations</h4>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,232 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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, useCallback, useEffect, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
import { isPageValid, updateAddField } from "../../createTenantSlice";
|
||||
import { clearValidationError } from "../../../utils";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const AWSKMSAdd = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const enableEncryption = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.enableEncryption
|
||||
);
|
||||
const encryptionType = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.encryptionType
|
||||
);
|
||||
const awsEndpoint = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.awsEndpoint
|
||||
);
|
||||
const awsRegion = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.awsRegion
|
||||
);
|
||||
const awsKMSKey = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.awsKMSKey
|
||||
);
|
||||
const awsAccessKey = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.awsAccessKey
|
||||
);
|
||||
const awsSecretKey = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.awsSecretKey
|
||||
);
|
||||
const awsToken = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.awsToken
|
||||
);
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let encryptionValidation: IValidation[] = [];
|
||||
|
||||
if (enableEncryption) {
|
||||
if (encryptionType === "aws") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "aws_endpoint",
|
||||
required: true,
|
||||
value: awsEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "aws_region",
|
||||
required: true,
|
||||
value: awsRegion,
|
||||
},
|
||||
{
|
||||
fieldKey: "aws_accessKey",
|
||||
required: true,
|
||||
value: awsAccessKey,
|
||||
},
|
||||
{
|
||||
fieldKey: "aws_secretKey",
|
||||
required: true,
|
||||
value: awsSecretKey,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(encryptionValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "encryption",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
enableEncryption,
|
||||
encryptionType,
|
||||
awsEndpoint,
|
||||
awsRegion,
|
||||
awsSecretKey,
|
||||
awsAccessKey,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
// Common
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({ pageName: "encryption", field: field, value: value })
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_endpoint"
|
||||
name="aws_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsEndpoint", e.target.value);
|
||||
cleanValidation("aws_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={awsEndpoint}
|
||||
error={validationErrors["aws_endpoint"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_region"
|
||||
name="aws_region"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsRegion", e.target.value);
|
||||
cleanValidation("aws_region");
|
||||
}}
|
||||
label="Region"
|
||||
value={awsRegion}
|
||||
error={validationErrors["aws_region"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_kmsKey"
|
||||
name="aws_kmsKey"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsKMSKey", e.target.value);
|
||||
}}
|
||||
label="KMS Key"
|
||||
value={awsKMSKey}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>Credentials</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_accessKey"
|
||||
name="aws_accessKey"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsAccessKey", e.target.value);
|
||||
cleanValidation("aws_accessKey");
|
||||
}}
|
||||
label="Access Key"
|
||||
value={awsAccessKey}
|
||||
error={validationErrors["aws_accessKey"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_secretKey"
|
||||
name="aws_secretKey"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsSecretKey", e.target.value);
|
||||
cleanValidation("aws_secretKey");
|
||||
}}
|
||||
label="Secret Key"
|
||||
value={awsSecretKey}
|
||||
error={validationErrors["aws_secretKey"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="aws_token"
|
||||
name="aws_token"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("awsToken", e.target.value);
|
||||
}}
|
||||
label="Token"
|
||||
value={awsToken}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default AWSKMSAdd;
|
||||
@@ -0,0 +1,202 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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, useCallback, useEffect, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
import { isPageValid, updateAddField } from "../../createTenantSlice";
|
||||
import { clearValidationError } from "../../../utils";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const AzureKMSAdd = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const enableEncryption = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.enableEncryption
|
||||
);
|
||||
const encryptionType = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.encryptionType
|
||||
);
|
||||
|
||||
const azureEndpoint = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.azureEndpoint
|
||||
);
|
||||
const azureTenantID = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.azureTenantID
|
||||
);
|
||||
const azureClientID = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.azureClientID
|
||||
);
|
||||
const azureClientSecret = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.azureClientSecret
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let encryptionValidation: IValidation[] = [];
|
||||
|
||||
if (enableEncryption) {
|
||||
if (encryptionType === "azure") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "azure_endpoint",
|
||||
required: true,
|
||||
value: azureEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "azure_tenant_id",
|
||||
required: true,
|
||||
value: azureTenantID,
|
||||
},
|
||||
{
|
||||
fieldKey: "azure_client_id",
|
||||
required: true,
|
||||
value: azureClientID,
|
||||
},
|
||||
{
|
||||
fieldKey: "azure_client_secret",
|
||||
required: true,
|
||||
value: azureClientSecret,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(encryptionValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "encryption",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
enableEncryption,
|
||||
encryptionType,
|
||||
azureEndpoint,
|
||||
azureTenantID,
|
||||
azureClientID,
|
||||
azureClientSecret,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
// Common
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({ pageName: "encryption", field: field, value: value })
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_endpoint"
|
||||
name="azure_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureEndpoint", e.target.value);
|
||||
cleanValidation("azure_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={azureEndpoint}
|
||||
error={validationErrors["azure_endpoint"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>Credentials</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_tenant_id"
|
||||
name="azure_tenant_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureTenantID", e.target.value);
|
||||
cleanValidation("azure_tenant_id");
|
||||
}}
|
||||
label="Tenant ID"
|
||||
value={azureTenantID}
|
||||
error={validationErrors["azure_tenant_id"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_client_id"
|
||||
name="azure_client_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureClientID", e.target.value);
|
||||
cleanValidation("azure_client_id");
|
||||
}}
|
||||
label="Client ID"
|
||||
value={azureClientID}
|
||||
error={validationErrors["azure_client_id"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="azure_client_secret"
|
||||
name="azure_client_secret"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("azureClientSecret", e.target.value);
|
||||
cleanValidation("azure_client_secret");
|
||||
}}
|
||||
label="Client Secret"
|
||||
value={azureClientSecret}
|
||||
error={validationErrors["azure_client_secret"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default AzureKMSAdd;
|
||||
@@ -0,0 +1,152 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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, useCallback } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { updateAddField } from "../../createTenantSlice";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const GCPKMSAdd = () => {
|
||||
const classes = useStyles();
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const gcpProjectID = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpProjectID
|
||||
);
|
||||
const gcpEndpoint = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpEndpoint
|
||||
);
|
||||
const gcpClientEmail = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpClientEmail
|
||||
);
|
||||
const gcpClientID = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpClientID
|
||||
);
|
||||
const gcpPrivateKeyID = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpPrivateKeyID
|
||||
);
|
||||
const gcpPrivateKey = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gcpPrivateKey
|
||||
);
|
||||
|
||||
// Common
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({ pageName: "encryption", field: field, value: value })
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_project_id"
|
||||
name="gcp_project_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpProjectID", e.target.value);
|
||||
}}
|
||||
label="Project ID"
|
||||
value={gcpProjectID}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_endpoint"
|
||||
name="gcp_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpEndpoint", e.target.value);
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={gcpEndpoint}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>Credentials</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_client_email"
|
||||
name="gcp_client_email"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpClientEmail", e.target.value);
|
||||
}}
|
||||
label="Client Email"
|
||||
value={gcpClientEmail}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_client_id"
|
||||
name="gcp_client_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpClientID", e.target.value);
|
||||
}}
|
||||
label="Client ID"
|
||||
value={gcpClientID}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_private_key_id"
|
||||
name="gcp_private_key_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpPrivateKeyID", e.target.value);
|
||||
}}
|
||||
label="Private Key ID"
|
||||
value={gcpPrivateKeyID}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gcp_private_key"
|
||||
name="gcp_private_key"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gcpPrivateKey", e.target.value);
|
||||
}}
|
||||
label="Private Key"
|
||||
value={gcpPrivateKey}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default GCPKMSAdd;
|
||||
@@ -0,0 +1,252 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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, useCallback, useEffect, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import FileSelector from "../../../../Common/FormComponents/FileSelector/FileSelector";
|
||||
import {
|
||||
addFileGemaltoCa,
|
||||
isPageValid,
|
||||
updateAddField,
|
||||
} from "../../createTenantSlice";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
import { clearValidationError } from "../../../utils";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const GemaltoKMSAdd = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const enableEncryption = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.enableEncryption
|
||||
);
|
||||
const encryptionType = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.encryptionType
|
||||
);
|
||||
const gemaltoCA = useSelector(
|
||||
(state: AppState) => state.createTenant.certificates.gemaltoCA
|
||||
);
|
||||
const gemaltoEndpoint = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gemaltoEndpoint
|
||||
);
|
||||
const gemaltoToken = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gemaltoToken
|
||||
);
|
||||
const gemaltoDomain = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gemaltoDomain
|
||||
);
|
||||
const gemaltoRetry = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.gemaltoRetry
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let encryptionValidation: IValidation[] = [];
|
||||
|
||||
if (enableEncryption) {
|
||||
if (encryptionType === "gemalto") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "gemalto_endpoint",
|
||||
required: true,
|
||||
value: gemaltoEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "gemalto_token",
|
||||
required: true,
|
||||
value: gemaltoToken,
|
||||
},
|
||||
{
|
||||
fieldKey: "gemalto_domain",
|
||||
required: true,
|
||||
value: gemaltoDomain,
|
||||
},
|
||||
{
|
||||
fieldKey: "gemalto_retry",
|
||||
required: false,
|
||||
value: gemaltoRetry,
|
||||
customValidation: parseInt(gemaltoRetry) < 0,
|
||||
customValidationMessage: "Value needs to be 0 or greater",
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(encryptionValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "encryption",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
enableEncryption,
|
||||
encryptionType,
|
||||
gemaltoEndpoint,
|
||||
gemaltoToken,
|
||||
gemaltoDomain,
|
||||
gemaltoRetry,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
// Common
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({ pageName: "encryption", field: field, value: value })
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gemalto_endpoint"
|
||||
name="gemalto_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoEndpoint", e.target.value);
|
||||
cleanValidation("gemalto_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={gemaltoEndpoint}
|
||||
error={validationErrors["gemalto_endpoint"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
style={{
|
||||
marginBottom: 15,
|
||||
}}
|
||||
>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>Credentials</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gemalto_token"
|
||||
name="gemalto_token"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoToken", e.target.value);
|
||||
cleanValidation("gemalto_token");
|
||||
}}
|
||||
label="Token"
|
||||
value={gemaltoToken}
|
||||
error={validationErrors["gemalto_token"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="gemalto_domain"
|
||||
name="gemalto_domain"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoDomain", e.target.value);
|
||||
cleanValidation("gemalto_domain");
|
||||
}}
|
||||
label="Domain"
|
||||
value={gemaltoDomain}
|
||||
error={validationErrors["gemalto_domain"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id="gemalto_retry"
|
||||
name="gemalto_retry"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("gemaltoRetry", e.target.value);
|
||||
cleanValidation("gemalto_retry");
|
||||
}}
|
||||
label="Retry (seconds)"
|
||||
value={gemaltoRetry}
|
||||
error={validationErrors["gemalto_retry"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
style={{
|
||||
marginBottom: 15,
|
||||
}}
|
||||
>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Custom CA Root certificate verification
|
||||
</legend>
|
||||
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileGemaltoCa({
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("gemalto_ca");
|
||||
}}
|
||||
accept=".cer,.crt,.cert,.pem"
|
||||
id="gemalto_ca"
|
||||
name="gemalto_ca"
|
||||
label="CA"
|
||||
value={gemaltoCA.cert}
|
||||
/>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default GemaltoKMSAdd;
|
||||
@@ -0,0 +1,373 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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, useCallback, useEffect, useState } from "react";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
|
||||
import FileSelector from "../../../../Common/FormComponents/FileSelector/FileSelector";
|
||||
import {
|
||||
addFileVaultCa,
|
||||
addFileVaultCert,
|
||||
isPageValid,
|
||||
updateAddField,
|
||||
} from "../../createTenantSlice";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
import { clearValidationError } from "../../../utils";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const VaultKMSAdd = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const enableEncryption = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.enableEncryption
|
||||
);
|
||||
const encryptionType = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.encryptionType
|
||||
);
|
||||
|
||||
const vaultEndpoint = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultEndpoint
|
||||
);
|
||||
const vaultEngine = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultEngine
|
||||
);
|
||||
const vaultNamespace = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultNamespace
|
||||
);
|
||||
const vaultPrefix = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultPrefix
|
||||
);
|
||||
const vaultAppRoleEngine = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultAppRoleEngine
|
||||
);
|
||||
const vaultId = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultId
|
||||
);
|
||||
const vaultSecret = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultSecret
|
||||
);
|
||||
const vaultRetry = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultRetry
|
||||
);
|
||||
const vaultPing = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.encryption.vaultPing
|
||||
);
|
||||
const vaultCertificate = useSelector(
|
||||
(state: AppState) => state.createTenant.certificates.vaultCertificate
|
||||
);
|
||||
const vaultCA = useSelector(
|
||||
(state: AppState) => state.createTenant.certificates.vaultCA
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let encryptionValidation: IValidation[] = [];
|
||||
|
||||
if (enableEncryption) {
|
||||
if (encryptionType === "vault") {
|
||||
encryptionValidation = [
|
||||
...encryptionValidation,
|
||||
{
|
||||
fieldKey: "vault_endpoint",
|
||||
required: true,
|
||||
value: vaultEndpoint,
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_id",
|
||||
required: true,
|
||||
value: vaultId,
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_secret",
|
||||
required: true,
|
||||
value: vaultSecret,
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_ping",
|
||||
required: false,
|
||||
value: vaultPing,
|
||||
customValidation: parseInt(vaultPing) < 0,
|
||||
customValidationMessage: "Value needs to be 0 or greater",
|
||||
},
|
||||
{
|
||||
fieldKey: "vault_retry",
|
||||
required: false,
|
||||
value: vaultRetry,
|
||||
customValidation: parseInt(vaultRetry) < 0,
|
||||
customValidationMessage: "Value needs to be 0 or greater",
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(encryptionValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "encryption",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
enableEncryption,
|
||||
encryptionType,
|
||||
vaultEndpoint,
|
||||
vaultEngine,
|
||||
vaultId,
|
||||
vaultSecret,
|
||||
vaultPing,
|
||||
vaultRetry,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
// Common
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({ pageName: "encryption", field: field, value: value })
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_endpoint"
|
||||
name="vault_endpoint"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultEndpoint", e.target.value);
|
||||
cleanValidation("vault_endpoint");
|
||||
}}
|
||||
label="Endpoint"
|
||||
value={vaultEndpoint}
|
||||
error={validationErrors["vault_endpoint"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_engine"
|
||||
name="vault_engine"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultEngine", e.target.value);
|
||||
cleanValidation("vault_engine");
|
||||
}}
|
||||
label="Engine"
|
||||
value={vaultEngine}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_namespace"
|
||||
name="vault_namespace"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultNamespace", e.target.value);
|
||||
}}
|
||||
label="Namespace"
|
||||
value={vaultNamespace}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_prefix"
|
||||
name="vault_prefix"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultPrefix", e.target.value);
|
||||
}}
|
||||
label="Prefix"
|
||||
value={vaultPrefix}
|
||||
/>
|
||||
</Grid>
|
||||
|
||||
<Grid item xs={12}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>App Role</legend>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_approle_engine"
|
||||
name="vault_approle_engine"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultAppRoleEngine", e.target.value);
|
||||
}}
|
||||
label="Engine"
|
||||
value={vaultAppRoleEngine}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_id"
|
||||
name="vault_id"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultId", e.target.value);
|
||||
cleanValidation("vault_id");
|
||||
}}
|
||||
label="AppRole ID"
|
||||
value={vaultId}
|
||||
error={validationErrors["vault_id"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="vault_secret"
|
||||
name="vault_secret"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultSecret", e.target.value);
|
||||
cleanValidation("vault_secret");
|
||||
}}
|
||||
label="AppRole Secret"
|
||||
value={vaultSecret}
|
||||
error={validationErrors["vault_secret"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id="vault_retry"
|
||||
name="vault_retry"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultRetry", e.target.value);
|
||||
cleanValidation("vault_retry");
|
||||
}}
|
||||
label="Retry (Seconds)"
|
||||
value={vaultRetry}
|
||||
error={validationErrors["vault_retry"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
|
||||
<Grid container className={classes.mutualTlsConfig}>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
Mutual TLS authentication (optional)
|
||||
</legend>
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileVaultCert({
|
||||
key: "key",
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("vault_key");
|
||||
}}
|
||||
accept=".key,.pem"
|
||||
id="vault_key"
|
||||
name="vault_key"
|
||||
label="Key"
|
||||
value={vaultCertificate.key}
|
||||
/>
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileVaultCert({
|
||||
key: "cert",
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("vault_cert");
|
||||
}}
|
||||
accept=".cer,.crt,.cert,.pem"
|
||||
id="vault_cert"
|
||||
name="vault_cert"
|
||||
label="Cert"
|
||||
value={vaultCertificate.cert}
|
||||
/>
|
||||
<FileSelector
|
||||
onChange={(encodedValue, fileName) => {
|
||||
dispatch(
|
||||
addFileVaultCa({
|
||||
fileName: fileName,
|
||||
value: encodedValue,
|
||||
})
|
||||
);
|
||||
cleanValidation("vault_ca");
|
||||
}}
|
||||
accept=".cer,.crt,.cert,.pem"
|
||||
id="vault_ca"
|
||||
name="vault_ca"
|
||||
label="CA"
|
||||
value={vaultCA.cert}
|
||||
/>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
<Grid
|
||||
item
|
||||
xs={12}
|
||||
className={classes.formFieldRow}
|
||||
style={{ marginTop: 15 }}
|
||||
>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>Status</legend>
|
||||
<InputBoxWrapper
|
||||
type="number"
|
||||
min="0"
|
||||
id="vault_ping"
|
||||
name="vault_ping"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("vaultPing", e.target.value);
|
||||
cleanValidation("vault_ping");
|
||||
}}
|
||||
label="Ping (Seconds)"
|
||||
value={vaultPing}
|
||||
error={validationErrors["vault_ping"] || ""}
|
||||
/>
|
||||
</fieldset>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default VaultKMSAdd;
|
||||
@@ -14,67 +14,26 @@
|
||||
// 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, useCallback, useEffect, useState } from "react";
|
||||
import React from "react";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { Grid, IconButton, Paper, Tooltip, Typography } from "@mui/material";
|
||||
import CasinoIcon from "@mui/icons-material/Casino";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import { Grid, Paper } from "@mui/material";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../Common/FormComponents/common/styleLibrary";
|
||||
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../utils/validationFunctions";
|
||||
import { AppState } from "../../../../../store";
|
||||
import { clearValidationError, getRandomString } from "../../utils";
|
||||
import RadioGroupSelector from "../../../Common/FormComponents/RadioGroupSelector/RadioGroupSelector";
|
||||
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import RemoveIcon from "../../../../../icons/RemoveIcon";
|
||||
import { isPageValid, updateAddField } from "../../tenantsSlice";
|
||||
import { setIDP } from "../createTenantSlice";
|
||||
import IDPActiveDirectory from "./IdentityProvider/IDPActiveDirectory";
|
||||
import IDPOpenID from "./IdentityProvider/IDPOpenID";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import IDPBuiltIn from "./IdentityProvider/IDPBuiltIn";
|
||||
|
||||
interface IIdentityProviderProps {
|
||||
classes: any;
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
shortened: {
|
||||
gridTemplateColumns: "auto auto 50px 50px",
|
||||
display: "grid",
|
||||
gridGap: 15,
|
||||
marginBottom: 10,
|
||||
"& input": {
|
||||
fontWeight: 400,
|
||||
},
|
||||
},
|
||||
buttonTray: {
|
||||
marginLeft: 10,
|
||||
display: "flex",
|
||||
height: 38,
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
overlayAction: {
|
||||
marginLeft: 10,
|
||||
"& svg": {
|
||||
maxWidth: 15,
|
||||
maxHeight: 15,
|
||||
},
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
protocolRadioOptions: {
|
||||
display: "flex",
|
||||
flexFlow: "column",
|
||||
@@ -89,374 +48,20 @@ const styles = (theme: Theme) =>
|
||||
alignItems: "baseline",
|
||||
},
|
||||
},
|
||||
adUserDnRows: {
|
||||
display: "flex",
|
||||
},
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const IdentityProvider = ({ classes }: IIdentityProviderProps) => {
|
||||
const IdentityProvider = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const idpSelection = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.idpSelection
|
||||
);
|
||||
const accessKeys = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.accessKeys
|
||||
);
|
||||
const secretKeys = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.secretKeys
|
||||
);
|
||||
const openIDConfigurationURL = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.openIDConfigurationURL
|
||||
);
|
||||
const openIDClientID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.openIDClientID
|
||||
);
|
||||
const openIDSecretID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.openIDSecretID
|
||||
);
|
||||
const openIDCallbackURL = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.openIDCallbackURL
|
||||
);
|
||||
const openIDClaimName = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.openIDClaimName
|
||||
);
|
||||
const openIDScopes = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.openIDScopes
|
||||
);
|
||||
const ADURL = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADURL
|
||||
);
|
||||
const ADSkipTLS = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADSkipTLS
|
||||
);
|
||||
const ADServerInsecure = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADServerInsecure
|
||||
);
|
||||
const ADGroupSearchBaseDN = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADGroupSearchBaseDN
|
||||
);
|
||||
const ADGroupSearchFilter = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADGroupSearchFilter
|
||||
);
|
||||
const ADUserDNs = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADUserDNs
|
||||
);
|
||||
const ADLookupBindDN = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADLookupBindDN
|
||||
);
|
||||
const ADLookupBindPassword = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADLookupBindPassword
|
||||
);
|
||||
const ADUserDNSearchBaseDN = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADUserDNSearchBaseDN
|
||||
);
|
||||
const ADUserDNSearchFilter = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADUserDNSearchFilter
|
||||
);
|
||||
const ADServerStartTLS = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.identityProvider.ADServerStartTLS
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.idpSelection
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({
|
||||
pageName: "identityProvider",
|
||||
field: field,
|
||||
value: value,
|
||||
})
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
const updateUserField = (index: number, value: string) => {
|
||||
const newUserField = [...accessKeys];
|
||||
newUserField[index] = value;
|
||||
updateField("accessKeys", newUserField);
|
||||
};
|
||||
const updatePwordField = (index: number, value: string) => {
|
||||
const newUserField = [...secretKeys];
|
||||
newUserField[index] = value;
|
||||
updateField("secretKeys", newUserField);
|
||||
};
|
||||
const updateADUserField = (index: number, value: string) => {
|
||||
const newADUserDNsField = [...ADUserDNs];
|
||||
newADUserDNsField[index] = value;
|
||||
updateField("ADUserDNs", newADUserDNsField);
|
||||
};
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
// Validation
|
||||
|
||||
useEffect(() => {
|
||||
let customIDPValidation: IValidation[] = [];
|
||||
|
||||
if (idpSelection === "Built-in") {
|
||||
customIDPValidation = [...customIDPValidation];
|
||||
for (var i = 0; i < accessKeys.length; i++) {
|
||||
customIDPValidation.push({
|
||||
fieldKey: `accesskey-${i.toString()}`,
|
||||
required: true,
|
||||
value: accessKeys[i],
|
||||
pattern: /^[a-zA-Z0-9-]{8,63}$/,
|
||||
customPatternMessage: "Keys must be at least length 8",
|
||||
});
|
||||
customIDPValidation.push({
|
||||
fieldKey: `secretkey-${i.toString()}`,
|
||||
required: true,
|
||||
value: secretKeys[i],
|
||||
pattern: /^[a-zA-Z0-9-]{8,63}$/,
|
||||
customPatternMessage: "Keys must be at least length 8",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (idpSelection === "OpenID") {
|
||||
customIDPValidation = [
|
||||
...customIDPValidation,
|
||||
{
|
||||
fieldKey: "openID_CONFIGURATION_URL",
|
||||
required: true,
|
||||
value: openIDConfigurationURL,
|
||||
},
|
||||
{
|
||||
fieldKey: "openID_clientID",
|
||||
required: true,
|
||||
value: openIDClientID,
|
||||
},
|
||||
{
|
||||
fieldKey: "openID_secretID",
|
||||
required: true,
|
||||
value: openIDSecretID,
|
||||
},
|
||||
{
|
||||
fieldKey: "openID_claimName",
|
||||
required: true,
|
||||
value: openIDClaimName,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
if (idpSelection === "AD") {
|
||||
customIDPValidation = [
|
||||
...customIDPValidation,
|
||||
{
|
||||
fieldKey: "AD_URL",
|
||||
required: true,
|
||||
value: ADURL,
|
||||
},
|
||||
{
|
||||
fieldKey: "ad_lookupBindDN",
|
||||
required: true,
|
||||
value: ADLookupBindDN,
|
||||
},
|
||||
];
|
||||
// validate user DNs
|
||||
for (let i = 0; i < ADUserDNs.length; i++) {
|
||||
customIDPValidation.push({
|
||||
fieldKey: `ad-userdn-${i.toString()}`,
|
||||
required: true,
|
||||
value: ADUserDNs[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(customIDPValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "identityProvider",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
ADLookupBindDN,
|
||||
idpSelection,
|
||||
accessKeys,
|
||||
secretKeys,
|
||||
openIDClientID,
|
||||
openIDSecretID,
|
||||
ADURL,
|
||||
ADGroupSearchBaseDN,
|
||||
ADGroupSearchFilter,
|
||||
ADUserDNs,
|
||||
dispatch,
|
||||
openIDConfigurationURL,
|
||||
openIDClaimName,
|
||||
]);
|
||||
let inputs = null;
|
||||
if (idpSelection === "Built-in") {
|
||||
inputs = accessKeys.map((_, index) => {
|
||||
return (
|
||||
<Fragment key={`identityField-${index.toString()}`}>
|
||||
<div className={classes.shortened}>
|
||||
<InputBoxWrapper
|
||||
id={`accesskey-${index.toString()}`}
|
||||
label={""}
|
||||
placeholder={"Access Key"}
|
||||
name={`accesskey-${index.toString()}`}
|
||||
value={accessKeys[index]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateUserField(index, e.target.value);
|
||||
cleanValidation(`accesskey-${index.toString()}`);
|
||||
}}
|
||||
index={index}
|
||||
key={`csv-accesskey-${index.toString()}`}
|
||||
error={validationErrors[`accesskey-${index.toString()}`] || ""}
|
||||
/>
|
||||
<InputBoxWrapper
|
||||
id={`secretkey-${index.toString()}`}
|
||||
label={""}
|
||||
placeholder={"Secret Key"}
|
||||
name={`secretkey-${index.toString()}`}
|
||||
value={secretKeys[index]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updatePwordField(index, e.target.value);
|
||||
cleanValidation(`secretkey-${index.toString()}`);
|
||||
}}
|
||||
index={index}
|
||||
key={`csv-secretkey-${index.toString()}`}
|
||||
error={validationErrors[`secretkey-${index.toString()}`] || ""}
|
||||
/>
|
||||
<div className={classes.buttonTray}>
|
||||
<Tooltip title="Add User" aria-label="add">
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
accessKeys.push("");
|
||||
secretKeys.push("");
|
||||
updateUserField(accessKeys.length - 1, "");
|
||||
updatePwordField(secretKeys.length - 1, "");
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip title="Remove" aria-label="add">
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
if (accessKeys.length > 1) {
|
||||
accessKeys.splice(index, 1);
|
||||
secretKeys.splice(index, 1);
|
||||
updateUserField(
|
||||
accessKeys.length - 1,
|
||||
accessKeys[accessKeys.length - 1]
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip title="Randomize Credentials" aria-label="add">
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
updateUserField(index, getRandomString(16));
|
||||
updatePwordField(index, getRandomString(32));
|
||||
}}
|
||||
size={"small"}
|
||||
>
|
||||
<CasinoIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
if (idpSelection === "AD") {
|
||||
inputs = ADUserDNs.map((_, index) => {
|
||||
return (
|
||||
<Fragment key={`identityField-${index.toString()}`}>
|
||||
<div className={classes.adUserDnRows}>
|
||||
<InputBoxWrapper
|
||||
id={`ad-userdn-${index.toString()}`}
|
||||
label={""}
|
||||
placeholder=""
|
||||
name={`ad-userdn-${index.toString()}`}
|
||||
value={ADUserDNs[index]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateADUserField(index, e.target.value);
|
||||
cleanValidation(`ad-userdn-${index.toString()}`);
|
||||
}}
|
||||
index={index}
|
||||
key={`csv-ad-userdn-${index.toString()}`}
|
||||
error={validationErrors[`ad-userdn-${index.toString()}`] || ""}
|
||||
/>
|
||||
<div className={classes.buttonTray}>
|
||||
<Tooltip title="Add User" aria-label="add">
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
ADUserDNs.push("");
|
||||
updateADUserField(ADUserDNs.length - 1, "");
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Remove" aria-label="add">
|
||||
<IconButton
|
||||
size={"small"}
|
||||
style={{ marginLeft: 16 }}
|
||||
onClick={() => {
|
||||
if (ADUserDNs.length > 1) {
|
||||
ADUserDNs.splice(index, 1);
|
||||
updateUserField(
|
||||
ADUserDNs.length - 1,
|
||||
ADUserDNs[ADUserDNs.length - 1]
|
||||
);
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
});
|
||||
}
|
||||
return (
|
||||
<Paper className={classes.paperWrapper}>
|
||||
<div className={classes.headerElement}>
|
||||
@@ -474,7 +79,7 @@ const IdentityProvider = ({ classes }: IIdentityProviderProps) => {
|
||||
name="idp-options"
|
||||
label=" "
|
||||
onChange={(e) => {
|
||||
updateField("idpSelection", e.target.value);
|
||||
dispatch(setIDP(e.target.value));
|
||||
}}
|
||||
selectorOptions={[
|
||||
{ label: "Built-in", value: "Built-in" },
|
||||
@@ -483,258 +88,11 @@ const IdentityProvider = ({ classes }: IIdentityProviderProps) => {
|
||||
]}
|
||||
/>
|
||||
</Grid>
|
||||
{idpSelection === "Built-in" && (
|
||||
<Fragment>
|
||||
Add additional users
|
||||
{inputs}
|
||||
</Fragment>
|
||||
)}
|
||||
{idpSelection === "OpenID" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_CONFIGURATION_URL"
|
||||
name="openID_CONFIGURATION_URL"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDConfigurationURL", e.target.value);
|
||||
cleanValidation("openID_CONFIGURATION_URL");
|
||||
}}
|
||||
label="Configuration URL"
|
||||
value={openIDConfigurationURL}
|
||||
placeholder="https://your-identity-provider.com/.well-known/openid-configuration"
|
||||
error={validationErrors["openID_CONFIGURATION_URL"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_clientID"
|
||||
name="openID_clientID"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDClientID", e.target.value);
|
||||
cleanValidation("openID_clientID");
|
||||
}}
|
||||
label="Client ID"
|
||||
value={openIDClientID}
|
||||
error={validationErrors["openID_clientID"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_secretID"
|
||||
name="openID_secretID"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDSecretID", e.target.value);
|
||||
cleanValidation("openID_secretID");
|
||||
}}
|
||||
label="Secret ID"
|
||||
value={openIDSecretID}
|
||||
error={validationErrors["openID_secretID"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_callbackURL"
|
||||
name="openID_callbackURL"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDCallbackURL", e.target.value);
|
||||
cleanValidation("openID_callbackURL");
|
||||
}}
|
||||
label="Callback URL"
|
||||
value={openIDCallbackURL}
|
||||
placeholder="https://your-console-endpoint:9443/oauth_callback"
|
||||
error={validationErrors["openID_callbackURL"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_claimName"
|
||||
name="openID_claimName"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDClaimName", e.target.value);
|
||||
cleanValidation("openID_claimName");
|
||||
}}
|
||||
label="Claim Name"
|
||||
value={openIDClaimName}
|
||||
error={validationErrors["openID_claimName"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_scopes"
|
||||
name="openID_scopes"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDScopes", e.target.value);
|
||||
cleanValidation("openID_scopes");
|
||||
}}
|
||||
label="Scopes"
|
||||
value={openIDScopes}
|
||||
/>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
)}
|
||||
{idpSelection === "AD" && (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="AD_URL"
|
||||
name="AD_URL"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADURL", e.target.value);
|
||||
cleanValidation("AD_URL");
|
||||
}}
|
||||
label="LDAP Server Address"
|
||||
value={ADURL}
|
||||
placeholder="ldap-server:636"
|
||||
error={validationErrors["AD_URL"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<FormSwitchWrapper
|
||||
value="ad_skipTLS"
|
||||
id="ad_skipTLS"
|
||||
name="ad_skipTLS"
|
||||
checked={ADSkipTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
updateField("ADSkipTLS", checked);
|
||||
}}
|
||||
label={"Skip TLS Verification"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<FormSwitchWrapper
|
||||
value="ad_serverInsecure"
|
||||
id="ad_serverInsecure"
|
||||
name="ad_serverInsecure"
|
||||
checked={ADServerInsecure}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
updateField("ADServerInsecure", checked);
|
||||
}}
|
||||
label={"Server Insecure"}
|
||||
/>
|
||||
</Grid>
|
||||
{ADServerInsecure ? (
|
||||
<Grid item xs={12}>
|
||||
<Typography
|
||||
className={classes.error}
|
||||
variant="caption"
|
||||
display="block"
|
||||
gutterBottom
|
||||
>
|
||||
Warning: All traffic with Active Directory will be unencrypted
|
||||
</Typography>
|
||||
<br />
|
||||
</Grid>
|
||||
) : null}
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<FormSwitchWrapper
|
||||
value="ad_serverStartTLS"
|
||||
id="ad_serverStartTLS"
|
||||
name="ad_serverStartTLS"
|
||||
checked={ADServerStartTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
updateField("ADServerStartTLS", checked);
|
||||
}}
|
||||
label={"Start TLS connection to AD/LDAP server"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_lookupBindDN"
|
||||
name="ad_lookupBindDN"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADLookupBindDN", e.target.value);
|
||||
cleanValidation("ad_lookupBindDN");
|
||||
}}
|
||||
label="Lookup Bind DN"
|
||||
value={ADLookupBindDN}
|
||||
placeholder="cn=admin,dc=min,dc=io"
|
||||
error={validationErrors["ad_lookupBindDN"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_lookupBindPassword"
|
||||
name="ad_lookupBindPassword"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADLookupBindPassword", e.target.value);
|
||||
}}
|
||||
label="Lookup Bind Password"
|
||||
value={ADLookupBindPassword}
|
||||
placeholder="admin"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_userDNSearchBaseDN"
|
||||
name="ad_userDNSearchBaseDN"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADUserDNSearchBaseDN", e.target.value);
|
||||
}}
|
||||
label="User DN Search Base DN"
|
||||
value={ADUserDNSearchBaseDN}
|
||||
placeholder="dc=min,dc=io"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_userDNSearchFilter"
|
||||
name="ad_userDNSearchFilter"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADUserDNSearchFilter", e.target.value);
|
||||
}}
|
||||
label="User DN Search Filter"
|
||||
value={ADUserDNSearchFilter}
|
||||
placeholder="(sAMAcountName=%s)"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_groupSearchBaseDN"
|
||||
name="ad_groupSearchBaseDN"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADGroupSearchBaseDN", e.target.value);
|
||||
}}
|
||||
label="Group Search Base DN"
|
||||
value={ADGroupSearchBaseDN}
|
||||
placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_groupSearchFilter"
|
||||
name="ad_groupSearchFilter"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADGroupSearchFilter", e.target.value);
|
||||
}}
|
||||
label="Group Search Filter"
|
||||
value={ADGroupSearchFilter}
|
||||
placeholder="(&(objectclass=groupOfNames)(member=%s))"
|
||||
/>
|
||||
</Grid>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
List of user DNs (Distinguished Names) to be Tenant Administrators
|
||||
</legend>
|
||||
<Grid item xs={12}>
|
||||
{inputs}
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Fragment>
|
||||
)}
|
||||
{idpSelection === "Built-in" && <IDPBuiltIn />}
|
||||
{idpSelection === "OpenID" && <IDPOpenID />}
|
||||
{idpSelection === "AD" && <IDPActiveDirectory />}
|
||||
</Paper>
|
||||
);
|
||||
};
|
||||
|
||||
export default withStyles(styles)(IdentityProvider);
|
||||
export default IdentityProvider;
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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 { Grid, IconButton, Tooltip, Typography } from "@mui/material";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import FormSwitchWrapper from "../../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
addIDPADUsrAtIndex,
|
||||
isPageValid,
|
||||
removeIDPADUsrAtIndex,
|
||||
setIDPADUsrAtIndex,
|
||||
updateAddField,
|
||||
} from "../../createTenantSlice";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { clearValidationError } from "../../../utils";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import DeleteIcon from "@mui/icons-material/Delete";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
adUserDnRows: {
|
||||
display: "flex",
|
||||
},
|
||||
buttonTray: {
|
||||
marginLeft: 10,
|
||||
display: "flex",
|
||||
height: 38,
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
overlayAction: {
|
||||
marginLeft: 10,
|
||||
"& svg": {
|
||||
maxWidth: 15,
|
||||
maxHeight: 15,
|
||||
},
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const IDPActiveDirectory = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const idpSelection = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.idpSelection
|
||||
);
|
||||
const ADURL = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.ADURL
|
||||
);
|
||||
const ADSkipTLS = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.ADSkipTLS
|
||||
);
|
||||
const ADServerInsecure = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADServerInsecure
|
||||
);
|
||||
const ADGroupSearchBaseDN = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADGroupSearchBaseDN
|
||||
);
|
||||
const ADGroupSearchFilter = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADGroupSearchFilter
|
||||
);
|
||||
const ADUserDNs = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.ADUserDNs
|
||||
);
|
||||
const ADLookupBindDN = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADLookupBindDN
|
||||
);
|
||||
const ADLookupBindPassword = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADLookupBindPassword
|
||||
);
|
||||
const ADUserDNSearchBaseDN = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADUserDNSearchBaseDN
|
||||
);
|
||||
const ADUserDNSearchFilter = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADUserDNSearchFilter
|
||||
);
|
||||
const ADServerStartTLS = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.ADServerStartTLS
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({
|
||||
pageName: "identityProvider",
|
||||
field: field,
|
||||
value: value,
|
||||
})
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let customIDPValidation: IValidation[] = [];
|
||||
|
||||
if (idpSelection === "AD") {
|
||||
customIDPValidation = [
|
||||
...customIDPValidation,
|
||||
{
|
||||
fieldKey: "AD_URL",
|
||||
required: true,
|
||||
value: ADURL,
|
||||
},
|
||||
{
|
||||
fieldKey: "ad_lookupBindDN",
|
||||
required: true,
|
||||
value: ADLookupBindDN,
|
||||
},
|
||||
];
|
||||
// validate user DNs
|
||||
for (let i = 0; i < ADUserDNs.length; i++) {
|
||||
customIDPValidation.push({
|
||||
fieldKey: `ad-userdn-${i.toString()}`,
|
||||
required: true,
|
||||
value: ADUserDNs[i],
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(customIDPValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "identityProvider",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
ADLookupBindDN,
|
||||
idpSelection,
|
||||
ADURL,
|
||||
ADGroupSearchBaseDN,
|
||||
ADGroupSearchFilter,
|
||||
ADUserDNs,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="AD_URL"
|
||||
name="AD_URL"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADURL", e.target.value);
|
||||
cleanValidation("AD_URL");
|
||||
}}
|
||||
label="LDAP Server Address"
|
||||
value={ADURL}
|
||||
placeholder="ldap-server:636"
|
||||
error={validationErrors["AD_URL"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<FormSwitchWrapper
|
||||
value="ad_skipTLS"
|
||||
id="ad_skipTLS"
|
||||
name="ad_skipTLS"
|
||||
checked={ADSkipTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
updateField("ADSkipTLS", checked);
|
||||
}}
|
||||
label={"Skip TLS Verification"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<FormSwitchWrapper
|
||||
value="ad_serverInsecure"
|
||||
id="ad_serverInsecure"
|
||||
name="ad_serverInsecure"
|
||||
checked={ADServerInsecure}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
updateField("ADServerInsecure", checked);
|
||||
}}
|
||||
label={"Server Insecure"}
|
||||
/>
|
||||
</Grid>
|
||||
{ADServerInsecure ? (
|
||||
<Grid item xs={12}>
|
||||
<Typography
|
||||
className={classes.error}
|
||||
variant="caption"
|
||||
display="block"
|
||||
gutterBottom
|
||||
>
|
||||
Warning: All traffic with Active Directory will be unencrypted
|
||||
</Typography>
|
||||
<br />
|
||||
</Grid>
|
||||
) : null}
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<FormSwitchWrapper
|
||||
value="ad_serverStartTLS"
|
||||
id="ad_serverStartTLS"
|
||||
name="ad_serverStartTLS"
|
||||
checked={ADServerStartTLS}
|
||||
onChange={(e) => {
|
||||
const targetD = e.target;
|
||||
const checked = targetD.checked;
|
||||
updateField("ADServerStartTLS", checked);
|
||||
}}
|
||||
label={"Start TLS connection to AD/LDAP server"}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_lookupBindDN"
|
||||
name="ad_lookupBindDN"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADLookupBindDN", e.target.value);
|
||||
cleanValidation("ad_lookupBindDN");
|
||||
}}
|
||||
label="Lookup Bind DN"
|
||||
value={ADLookupBindDN}
|
||||
placeholder="cn=admin,dc=min,dc=io"
|
||||
error={validationErrors["ad_lookupBindDN"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_lookupBindPassword"
|
||||
name="ad_lookupBindPassword"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADLookupBindPassword", e.target.value);
|
||||
}}
|
||||
label="Lookup Bind Password"
|
||||
value={ADLookupBindPassword}
|
||||
placeholder="admin"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_userDNSearchBaseDN"
|
||||
name="ad_userDNSearchBaseDN"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADUserDNSearchBaseDN", e.target.value);
|
||||
}}
|
||||
label="User DN Search Base DN"
|
||||
value={ADUserDNSearchBaseDN}
|
||||
placeholder="dc=min,dc=io"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_userDNSearchFilter"
|
||||
name="ad_userDNSearchFilter"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADUserDNSearchFilter", e.target.value);
|
||||
}}
|
||||
label="User DN Search Filter"
|
||||
value={ADUserDNSearchFilter}
|
||||
placeholder="(sAMAcountName=%s)"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_groupSearchBaseDN"
|
||||
name="ad_groupSearchBaseDN"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADGroupSearchBaseDN", e.target.value);
|
||||
}}
|
||||
label="Group Search Base DN"
|
||||
value={ADGroupSearchBaseDN}
|
||||
placeholder="ou=hwengg,dc=min,dc=io;ou=swengg,dc=min,dc=io"
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="ad_groupSearchFilter"
|
||||
name="ad_groupSearchFilter"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("ADGroupSearchFilter", e.target.value);
|
||||
}}
|
||||
label="Group Search Filter"
|
||||
value={ADGroupSearchFilter}
|
||||
placeholder="(&(objectclass=groupOfNames)(member=%s))"
|
||||
/>
|
||||
</Grid>
|
||||
<fieldset className={classes.fieldGroup}>
|
||||
<legend className={classes.descriptionText}>
|
||||
List of user DNs (Distinguished Names) to be Tenant Administrators
|
||||
</legend>
|
||||
<Grid item xs={12}>
|
||||
{ADUserDNs.map((_, index) => {
|
||||
return (
|
||||
<Fragment key={`identityField-${index.toString()}`}>
|
||||
<div className={classes.adUserDnRows}>
|
||||
<InputBoxWrapper
|
||||
id={`ad-userdn-${index.toString()}`}
|
||||
label={""}
|
||||
placeholder=""
|
||||
name={`ad-userdn-${index.toString()}`}
|
||||
value={ADUserDNs[index]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(
|
||||
setIDPADUsrAtIndex({
|
||||
index: index,
|
||||
userDN: e.target.value,
|
||||
})
|
||||
);
|
||||
cleanValidation(`ad-userdn-${index.toString()}`);
|
||||
}}
|
||||
index={index}
|
||||
key={`csv-ad-userdn-${index.toString()}`}
|
||||
error={
|
||||
validationErrors[`ad-userdn-${index.toString()}`] || ""
|
||||
}
|
||||
/>
|
||||
<div className={classes.buttonTray}>
|
||||
<Tooltip title="Add User" aria-label="add">
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
dispatch(addIDPADUsrAtIndex());
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip title="Remove" aria-label="add">
|
||||
<IconButton
|
||||
size={"small"}
|
||||
style={{ marginLeft: 16 }}
|
||||
onClick={() => {
|
||||
if (ADUserDNs.length > 1) {
|
||||
dispatch(removeIDPADUsrAtIndex(index));
|
||||
}
|
||||
}}
|
||||
>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Grid>
|
||||
</fieldset>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default IDPActiveDirectory;
|
||||
@@ -0,0 +1,241 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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, useEffect, useState } from "react";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import {
|
||||
addIDPNewKeyPair,
|
||||
isPageValid,
|
||||
removeIDPKeyPairAtIndex,
|
||||
setIDPPwdAtIndex,
|
||||
setIDPUsrAtIndex,
|
||||
} from "../../createTenantSlice";
|
||||
import { IconButton, Tooltip } from "@mui/material";
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import RemoveIcon from "../../../../../../icons/RemoveIcon";
|
||||
import { clearValidationError, getRandomString } from "../../../utils";
|
||||
import CasinoIcon from "@mui/icons-material/Casino";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
buttonTray: {
|
||||
marginLeft: 10,
|
||||
display: "flex",
|
||||
height: 38,
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
overlayAction: {
|
||||
marginLeft: 10,
|
||||
"& svg": {
|
||||
maxWidth: 15,
|
||||
maxHeight: 15,
|
||||
},
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
shortened: {
|
||||
gridTemplateColumns: "auto auto 50px 50px",
|
||||
display: "grid",
|
||||
gridGap: 15,
|
||||
marginBottom: 10,
|
||||
"& input": {
|
||||
fontWeight: 400,
|
||||
},
|
||||
},
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const IDPBuiltIn = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const idpSelection = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.idpSelection
|
||||
);
|
||||
const accessKeys = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.accessKeys
|
||||
);
|
||||
const secretKeys = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.secretKeys
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let customIDPValidation: IValidation[] = [];
|
||||
|
||||
if (idpSelection === "Built-in") {
|
||||
customIDPValidation = [...customIDPValidation];
|
||||
for (var i = 0; i < accessKeys.length; i++) {
|
||||
customIDPValidation.push({
|
||||
fieldKey: `accesskey-${i.toString()}`,
|
||||
required: true,
|
||||
value: accessKeys[i],
|
||||
pattern: /^[a-zA-Z0-9-]{8,63}$/,
|
||||
customPatternMessage: "Keys must be at least length 8",
|
||||
});
|
||||
customIDPValidation.push({
|
||||
fieldKey: `secretkey-${i.toString()}`,
|
||||
required: true,
|
||||
value: secretKeys[i],
|
||||
pattern: /^[a-zA-Z0-9-]{8,63}$/,
|
||||
customPatternMessage: "Keys must be at least length 8",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(customIDPValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "identityProvider",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [idpSelection, accessKeys, secretKeys, dispatch]);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
Add additional users
|
||||
{accessKeys.map((_, index) => {
|
||||
return (
|
||||
<Fragment key={`identityField-${index.toString()}`}>
|
||||
<div className={classes.shortened}>
|
||||
<InputBoxWrapper
|
||||
id={`accesskey-${index.toString()}`}
|
||||
label={""}
|
||||
placeholder={"Access Key"}
|
||||
name={`accesskey-${index.toString()}`}
|
||||
value={accessKeys[index]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(
|
||||
setIDPUsrAtIndex({
|
||||
index,
|
||||
accessKey: e.target.value,
|
||||
})
|
||||
);
|
||||
cleanValidation(`accesskey-${index.toString()}`);
|
||||
}}
|
||||
index={index}
|
||||
key={`csv-accesskey-${index.toString()}`}
|
||||
error={validationErrors[`accesskey-${index.toString()}`] || ""}
|
||||
/>
|
||||
<InputBoxWrapper
|
||||
id={`secretkey-${index.toString()}`}
|
||||
label={""}
|
||||
placeholder={"Secret Key"}
|
||||
name={`secretkey-${index.toString()}`}
|
||||
value={secretKeys[index]}
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
dispatch(
|
||||
setIDPPwdAtIndex({
|
||||
index,
|
||||
secretKey: e.target.value,
|
||||
})
|
||||
);
|
||||
cleanValidation(`secretkey-${index.toString()}`);
|
||||
}}
|
||||
index={index}
|
||||
key={`csv-secretkey-${index.toString()}`}
|
||||
error={validationErrors[`secretkey-${index.toString()}`] || ""}
|
||||
/>
|
||||
<div className={classes.buttonTray}>
|
||||
<Tooltip title="Add User" aria-label="add">
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
dispatch(addIDPNewKeyPair());
|
||||
}}
|
||||
>
|
||||
<AddIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip title="Remove" aria-label="add">
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
dispatch(removeIDPKeyPairAtIndex(index));
|
||||
}}
|
||||
>
|
||||
<RemoveIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
<Tooltip title="Randomize Credentials" aria-label="add">
|
||||
<div className={classes.overlayAction}>
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
dispatch(
|
||||
setIDPUsrAtIndex({
|
||||
index,
|
||||
accessKey: getRandomString(16),
|
||||
})
|
||||
);
|
||||
dispatch(
|
||||
setIDPPwdAtIndex({
|
||||
index,
|
||||
secretKey: getRandomString(16),
|
||||
})
|
||||
);
|
||||
}}
|
||||
size={"small"}
|
||||
>
|
||||
<CasinoIcon />
|
||||
</IconButton>
|
||||
</div>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</Fragment>
|
||||
);
|
||||
})}
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default IDPBuiltIn;
|
||||
@@ -0,0 +1,253 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2022 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 { Grid } from "@mui/material";
|
||||
import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import React, { Fragment, useCallback, useEffect, useState } from "react";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import {
|
||||
createTenantCommon,
|
||||
formFieldStyles,
|
||||
modalBasic,
|
||||
wizardCommon,
|
||||
} from "../../../../Common/FormComponents/common/styleLibrary";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { isPageValid, updateAddField } from "../../createTenantSlice";
|
||||
import { clearValidationError } from "../../../utils";
|
||||
import {
|
||||
commonFormValidation,
|
||||
IValidation,
|
||||
} from "../../../../../../utils/validationFunctions";
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
buttonTray: {
|
||||
marginLeft: 10,
|
||||
display: "flex",
|
||||
height: 38,
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
overlayAction: {
|
||||
marginLeft: 10,
|
||||
"& svg": {
|
||||
maxWidth: 15,
|
||||
maxHeight: 15,
|
||||
},
|
||||
"& button": {
|
||||
background: "#EAEAEA",
|
||||
},
|
||||
},
|
||||
...createTenantCommon,
|
||||
...formFieldStyles,
|
||||
...modalBasic,
|
||||
...wizardCommon,
|
||||
})
|
||||
);
|
||||
|
||||
const IDPOpenID = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const idpSelection = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.idpSelection
|
||||
);
|
||||
const openIDConfigurationURL = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.openIDConfigurationURL
|
||||
);
|
||||
const openIDClientID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.openIDClientID
|
||||
);
|
||||
const openIDSecretID = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.openIDSecretID
|
||||
);
|
||||
const openIDCallbackURL = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.openIDCallbackURL
|
||||
);
|
||||
const openIDClaimName = useSelector(
|
||||
(state: AppState) =>
|
||||
state.createTenant.fields.identityProvider.openIDClaimName
|
||||
);
|
||||
const openIDScopes = useSelector(
|
||||
(state: AppState) => state.createTenant.fields.identityProvider.openIDScopes
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
const updateField = useCallback(
|
||||
(field: string, value: any) => {
|
||||
dispatch(
|
||||
updateAddField({
|
||||
pageName: "identityProvider",
|
||||
field: field,
|
||||
value: value,
|
||||
})
|
||||
);
|
||||
},
|
||||
[dispatch]
|
||||
);
|
||||
|
||||
const cleanValidation = (fieldName: string) => {
|
||||
setValidationErrors(clearValidationError(validationErrors, fieldName));
|
||||
};
|
||||
|
||||
// Validation
|
||||
useEffect(() => {
|
||||
let customIDPValidation: IValidation[] = [];
|
||||
|
||||
if (idpSelection === "OpenID") {
|
||||
customIDPValidation = [
|
||||
...customIDPValidation,
|
||||
{
|
||||
fieldKey: "openID_CONFIGURATION_URL",
|
||||
required: true,
|
||||
value: openIDConfigurationURL,
|
||||
},
|
||||
{
|
||||
fieldKey: "openID_clientID",
|
||||
required: true,
|
||||
value: openIDClientID,
|
||||
},
|
||||
{
|
||||
fieldKey: "openID_secretID",
|
||||
required: true,
|
||||
value: openIDSecretID,
|
||||
},
|
||||
{
|
||||
fieldKey: "openID_claimName",
|
||||
required: true,
|
||||
value: openIDClaimName,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const commonVal = commonFormValidation(customIDPValidation);
|
||||
|
||||
dispatch(
|
||||
isPageValid({
|
||||
pageName: "identityProvider",
|
||||
valid: Object.keys(commonVal).length === 0,
|
||||
})
|
||||
);
|
||||
|
||||
setValidationErrors(commonVal);
|
||||
}, [
|
||||
idpSelection,
|
||||
openIDClientID,
|
||||
openIDSecretID,
|
||||
openIDConfigurationURL,
|
||||
openIDClaimName,
|
||||
dispatch,
|
||||
]);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_CONFIGURATION_URL"
|
||||
name="openID_CONFIGURATION_URL"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDConfigurationURL", e.target.value);
|
||||
cleanValidation("openID_CONFIGURATION_URL");
|
||||
}}
|
||||
label="Configuration URL"
|
||||
value={openIDConfigurationURL}
|
||||
placeholder="https://your-identity-provider.com/.well-known/openid-configuration"
|
||||
error={validationErrors["openID_CONFIGURATION_URL"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_clientID"
|
||||
name="openID_clientID"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDClientID", e.target.value);
|
||||
cleanValidation("openID_clientID");
|
||||
}}
|
||||
label="Client ID"
|
||||
value={openIDClientID}
|
||||
error={validationErrors["openID_clientID"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_secretID"
|
||||
name="openID_secretID"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDSecretID", e.target.value);
|
||||
cleanValidation("openID_secretID");
|
||||
}}
|
||||
label="Secret ID"
|
||||
value={openIDSecretID}
|
||||
error={validationErrors["openID_secretID"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_callbackURL"
|
||||
name="openID_callbackURL"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDCallbackURL", e.target.value);
|
||||
cleanValidation("openID_callbackURL");
|
||||
}}
|
||||
label="Callback URL"
|
||||
value={openIDCallbackURL}
|
||||
placeholder="https://your-console-endpoint:9443/oauth_callback"
|
||||
error={validationErrors["openID_callbackURL"] || ""}
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_claimName"
|
||||
name="openID_claimName"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDClaimName", e.target.value);
|
||||
cleanValidation("openID_claimName");
|
||||
}}
|
||||
label="Claim Name"
|
||||
value={openIDClaimName}
|
||||
error={validationErrors["openID_claimName"] || ""}
|
||||
required
|
||||
/>
|
||||
</Grid>
|
||||
<Grid item xs={12} className={classes.formFieldRow}>
|
||||
<InputBoxWrapper
|
||||
id="openID_scopes"
|
||||
name="openID_scopes"
|
||||
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
updateField("openIDScopes", e.target.value);
|
||||
cleanValidation("openID_scopes");
|
||||
}}
|
||||
label="Scopes"
|
||||
value={openIDScopes}
|
||||
/>
|
||||
</Grid>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default IDPOpenID;
|
||||
@@ -33,7 +33,7 @@ import {
|
||||
} from "../../../../../utils/validationFunctions";
|
||||
import FormSwitchWrapper from "../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import InputBoxWrapper from "../../../Common/FormComponents/InputBoxWrapper/InputBoxWrapper";
|
||||
import { isPageValid, updateAddField } from "../../tenantsSlice";
|
||||
import { isPageValid, updateAddField } from "../createTenantSlice";
|
||||
|
||||
interface IImagesProps {
|
||||
classes: any;
|
||||
@@ -50,84 +50,75 @@ const Images = ({ classes }: IImagesProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const customImage = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.configure.customImage
|
||||
(state: AppState) => state.createTenant.fields.configure.customImage
|
||||
);
|
||||
const imageName = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.configure.imageName
|
||||
(state: AppState) => state.createTenant.fields.configure.imageName
|
||||
);
|
||||
const customDockerhub = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.customDockerhub
|
||||
(state: AppState) => state.createTenant.fields.configure.customDockerhub
|
||||
);
|
||||
const imageRegistry = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.imageRegistry
|
||||
(state: AppState) => state.createTenant.fields.configure.imageRegistry
|
||||
);
|
||||
const imageRegistryUsername = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.imageRegistryUsername
|
||||
state.createTenant.fields.configure.imageRegistryUsername
|
||||
);
|
||||
const imageRegistryPassword = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.imageRegistryPassword
|
||||
state.createTenant.fields.configure.imageRegistryPassword
|
||||
);
|
||||
|
||||
const prometheusCustom = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusEnabled
|
||||
(state: AppState) => state.createTenant.fields.configure.prometheusEnabled
|
||||
);
|
||||
const tenantCustom = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.tenantCustom
|
||||
(state: AppState) => state.createTenant.fields.configure.tenantCustom
|
||||
);
|
||||
const logSearchCustom = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchEnabled
|
||||
(state: AppState) => state.createTenant.fields.configure.logSearchEnabled
|
||||
);
|
||||
const logSearchVolumeSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchVolumeSize
|
||||
(state: AppState) => state.createTenant.fields.configure.logSearchVolumeSize
|
||||
);
|
||||
|
||||
const prometheusVolumeSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusVolumeSize
|
||||
state.createTenant.fields.configure.prometheusVolumeSize
|
||||
);
|
||||
|
||||
const logSearchSelectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchSelectedStorageClass
|
||||
state.createTenant.fields.configure.logSearchSelectedStorageClass
|
||||
);
|
||||
const logSearchImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchImage
|
||||
(state: AppState) => state.createTenant.fields.configure.logSearchImage
|
||||
);
|
||||
const kesImage = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.configure.kesImage
|
||||
(state: AppState) => state.createTenant.fields.configure.kesImage
|
||||
);
|
||||
const logSearchPostgresImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchPostgresImage
|
||||
state.createTenant.fields.configure.logSearchPostgresImage
|
||||
);
|
||||
const logSearchPostgresInitImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.logSearchPostgresInitImage
|
||||
state.createTenant.fields.configure.logSearchPostgresInitImage
|
||||
);
|
||||
const prometheusSelectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusSelectedStorageClass
|
||||
state.createTenant.fields.configure.prometheusSelectedStorageClass
|
||||
);
|
||||
const prometheusImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusImage
|
||||
(state: AppState) => state.createTenant.fields.configure.prometheusImage
|
||||
);
|
||||
const prometheusSidecarImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusSidecarImage
|
||||
state.createTenant.fields.configure.prometheusSidecarImage
|
||||
);
|
||||
const prometheusInitImage = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.configure.prometheusInitImage
|
||||
(state: AppState) => state.createTenant.fields.configure.prometheusInitImage
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
@@ -42,7 +42,7 @@ import {
|
||||
deleteKeyPair,
|
||||
isPageValid,
|
||||
updateAddField,
|
||||
} from "../../tenantsSlice";
|
||||
} from "../createTenantSlice";
|
||||
|
||||
interface ISecurityProps {
|
||||
classes: any;
|
||||
@@ -120,22 +120,19 @@ const Security = ({ classes }: ISecurityProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const enableTLS = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.security.enableTLS
|
||||
(state: AppState) => state.createTenant.fields.security.enableTLS
|
||||
);
|
||||
const enableAutoCert = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.security.enableAutoCert
|
||||
(state: AppState) => state.createTenant.fields.security.enableAutoCert
|
||||
);
|
||||
const enableCustomCerts = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.security.enableCustomCerts
|
||||
(state: AppState) => state.createTenant.fields.security.enableCustomCerts
|
||||
);
|
||||
const minioCertificates = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.certificates.minioCertificates
|
||||
(state: AppState) => state.createTenant.certificates.minioCertificates
|
||||
);
|
||||
const caCertificates = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.certificates.caCertificates
|
||||
(state: AppState) => state.createTenant.certificates.caCertificates
|
||||
);
|
||||
|
||||
// Common
|
||||
|
||||
@@ -52,32 +52,30 @@ const styles = (theme: Theme) =>
|
||||
|
||||
const SizePreview = ({ classes }: ISizePreviewProps) => {
|
||||
const nodes = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.nodes
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.nodes
|
||||
);
|
||||
const memoryNode = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesMemoryRequest
|
||||
state.createTenant.fields.tenantSize.resourcesMemoryRequest
|
||||
);
|
||||
const ecParity = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.ecParity
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParity
|
||||
);
|
||||
|
||||
const distribution = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.distribution
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.distribution
|
||||
);
|
||||
const ecParityCalc = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.ecParityCalc
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParityCalc
|
||||
);
|
||||
|
||||
const cpuToUse = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesCPURequest
|
||||
state.createTenant.fields.tenantSize.resourcesCPURequest
|
||||
);
|
||||
const integrationSelection = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.integrationSelection
|
||||
state.createTenant.fields.tenantSize.integrationSelection
|
||||
);
|
||||
|
||||
const usableInformation = ecParityCalc.storageFactors.find(
|
||||
|
||||
@@ -59,7 +59,8 @@ import {
|
||||
setStorageClassesList,
|
||||
setStorageType,
|
||||
updateAddField,
|
||||
} from "../../../tenantsSlice";
|
||||
} from "../../createTenantSlice";
|
||||
import { selFeatures } from "../../../../consoleSlice";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -84,25 +85,23 @@ const NameTenantMain = ({ classes, formToRender }: INameTenantMainScreen) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const tenantName = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.nameTenant.tenantName
|
||||
(state: AppState) => state.createTenant.fields.nameTenant.tenantName
|
||||
);
|
||||
const namespace = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.nameTenant.namespace
|
||||
(state: AppState) => state.createTenant.fields.nameTenant.namespace
|
||||
);
|
||||
const selectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass
|
||||
state.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const selectedStorageType = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageType
|
||||
state.createTenant.fields.nameTenant.selectedStorageType
|
||||
);
|
||||
const storageClasses = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.storageClasses
|
||||
);
|
||||
const features = useSelector(
|
||||
(state: AppState) => state.console.session.features
|
||||
(state: AppState) => state.createTenant.storageClasses
|
||||
);
|
||||
const features = useSelector(selFeatures);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
const [emptyNamespace, setEmptyNamespace] = useState<boolean>(true);
|
||||
|
||||
@@ -15,17 +15,14 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { connect } from "react-redux";
|
||||
import { useSelector } from "react-redux";
|
||||
import get from "lodash/get";
|
||||
import NameTenantMain from "./NameTenantMain";
|
||||
import { IMkEnvs, resourcesConfigurations } from "./utils";
|
||||
import { AppState } from "../../../../../../store";
|
||||
import { selFeatures } from "../../../../consoleSlice";
|
||||
|
||||
interface ITenantResources {
|
||||
features?: string[];
|
||||
}
|
||||
|
||||
const TenantResources = ({ features }: ITenantResources) => {
|
||||
const TenantResources = () => {
|
||||
const features = useSelector(selFeatures);
|
||||
const [formRender, setFormRender] = useState<IMkEnvs | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -55,10 +52,4 @@ const TenantResources = ({ features }: ITenantResources) => {
|
||||
return <NameTenantMain formToRender={formRender} />;
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
features: state.console.session.features,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default connector(TenantResources);
|
||||
export default TenantResources;
|
||||
|
||||
@@ -44,7 +44,7 @@ import SelectWrapper from "../../../../Common/FormComponents/SelectWrapper/Selec
|
||||
import TenantSizeResources from "./TenantSizeResources";
|
||||
import InputUnitMenu from "../../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import { IMkEnvs } from "./utils";
|
||||
import { isPageValid, updateAddField } from "../../../tenantsSlice";
|
||||
import { isPageValid, updateAddField } from "../../createTenantSlice";
|
||||
|
||||
interface ITenantSizeProps {
|
||||
classes: any;
|
||||
@@ -73,58 +73,51 @@ const TenantSize = ({ classes, formToRender }: ITenantSizeProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const volumeSize = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.volumeSize
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.volumeSize
|
||||
);
|
||||
const sizeFactor = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.sizeFactor
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.sizeFactor
|
||||
);
|
||||
const drivesPerServer = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.drivesPerServer
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.drivesPerServer
|
||||
);
|
||||
const nodes = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.nodes
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.nodes
|
||||
);
|
||||
const memoryNode = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.memoryNode
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.memoryNode
|
||||
);
|
||||
const ecParity = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.ecParity
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParity
|
||||
);
|
||||
const ecParityChoices = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.ecParityChoices
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParityChoices
|
||||
);
|
||||
const cleanECChoices = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.cleanECChoices
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.cleanECChoices
|
||||
);
|
||||
const resourcesSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesSize
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.resourcesSize
|
||||
);
|
||||
const distribution = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.distribution
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.distribution
|
||||
);
|
||||
const ecParityCalc = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.ecParityCalc
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParityCalc
|
||||
);
|
||||
const untouchedECField = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.untouchedECField
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.untouchedECField
|
||||
);
|
||||
const limitSize = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.limitSize
|
||||
(state: AppState) => state.createTenant.limitSize
|
||||
);
|
||||
const selectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass
|
||||
state.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const selectedStorageType = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageType
|
||||
state.createTenant.fields.nameTenant.selectedStorageType
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
@@ -41,7 +41,7 @@ import {
|
||||
IntegrationConfiguration,
|
||||
mkPanelConfigurations,
|
||||
} from "./utils";
|
||||
import { isPageValid, updateAddField } from "../../../tenantsSlice";
|
||||
import { isPageValid, updateAddField } from "../../createTenantSlice";
|
||||
|
||||
interface ITenantSizeAWSProps {
|
||||
classes: any;
|
||||
@@ -74,60 +74,54 @@ const TenantSizeMK = ({
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const volumeSize = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.volumeSize
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.volumeSize
|
||||
);
|
||||
const sizeFactor = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.sizeFactor
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.sizeFactor
|
||||
);
|
||||
const drivesPerServer = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.drivesPerServer
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.drivesPerServer
|
||||
);
|
||||
const nodes = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.nodes
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.nodes
|
||||
);
|
||||
const memoryNode = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.memoryNode
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.memoryNode
|
||||
);
|
||||
const ecParity = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.ecParity
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParity
|
||||
);
|
||||
const ecParityChoices = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.ecParityChoices
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParityChoices
|
||||
);
|
||||
const cleanECChoices = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.cleanECChoices
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.cleanECChoices
|
||||
);
|
||||
const resourcesSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesSize
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.resourcesSize
|
||||
);
|
||||
const distribution = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.distribution
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.distribution
|
||||
);
|
||||
const ecParityCalc = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.ecParityCalc
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.ecParityCalc
|
||||
);
|
||||
const cpuToUse = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.cpuToUse
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.cpuToUse
|
||||
);
|
||||
const maxCPUsUse = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.maxCPUsUse
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.maxCPUsUse
|
||||
);
|
||||
const integrationSelection = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.integrationSelection
|
||||
state.createTenant.fields.tenantSize.integrationSelection
|
||||
);
|
||||
const limitSize = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.limitSize
|
||||
(state: AppState) => state.createTenant.limitSize
|
||||
);
|
||||
const selectedStorageType = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageType
|
||||
state.createTenant.fields.nameTenant.selectedStorageType
|
||||
);
|
||||
|
||||
const [validationErrors, setValidationErrors] = useState<any>({});
|
||||
|
||||
@@ -33,7 +33,7 @@ import InputBoxWrapper from "../../../../Common/FormComponents/InputBoxWrapper/I
|
||||
import FormSwitchWrapper from "../../../../Common/FormComponents/FormSwitchWrapper/FormSwitchWrapper";
|
||||
import { floor } from "lodash";
|
||||
import InputUnitMenu from "../../../../Common/FormComponents/InputUnitMenu/InputUnitMenu";
|
||||
import { isPageValid, updateAddField } from "../../../tenantsSlice";
|
||||
import { isPageValid, updateAddField } from "../../createTenantSlice";
|
||||
|
||||
interface ITenantSizeResourcesProps {
|
||||
classes: any;
|
||||
@@ -66,62 +66,59 @@ ITenantSizeResourcesProps) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const nodes = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.nodes
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.nodes
|
||||
);
|
||||
|
||||
const resourcesSize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesSize
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.resourcesSize
|
||||
);
|
||||
const selectedStorageClass = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.nameTenant.selectedStorageClass
|
||||
state.createTenant.fields.nameTenant.selectedStorageClass
|
||||
);
|
||||
const maxCPUsUse = useSelector(
|
||||
(state: AppState) => state.tenants.createTenant.fields.tenantSize.maxCPUsUse
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.maxCPUsUse
|
||||
);
|
||||
const maxMemorySize = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.maxMemorySize
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.maxMemorySize
|
||||
);
|
||||
|
||||
const resourcesSpecifyLimit = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesSpecifyLimit
|
||||
state.createTenant.fields.tenantSize.resourcesSpecifyLimit
|
||||
);
|
||||
|
||||
const resourcesCPURequestError = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesCPURequestError
|
||||
state.createTenant.fields.tenantSize.resourcesCPURequestError
|
||||
);
|
||||
const resourcesCPURequest = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesCPURequest
|
||||
state.createTenant.fields.tenantSize.resourcesCPURequest
|
||||
);
|
||||
const resourcesCPULimitError = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesCPULimitError
|
||||
state.createTenant.fields.tenantSize.resourcesCPULimitError
|
||||
);
|
||||
const resourcesCPULimit = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesCPULimit
|
||||
(state: AppState) => state.createTenant.fields.tenantSize.resourcesCPULimit
|
||||
);
|
||||
|
||||
const resourcesMemoryRequestError = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesMemoryRequestError
|
||||
state.createTenant.fields.tenantSize.resourcesMemoryRequestError
|
||||
);
|
||||
const resourcesMemoryRequest = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesMemoryRequest
|
||||
state.createTenant.fields.tenantSize.resourcesMemoryRequest
|
||||
);
|
||||
const resourcesMemoryLimitError = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesMemoryLimitError
|
||||
state.createTenant.fields.tenantSize.resourcesMemoryLimitError
|
||||
);
|
||||
const resourcesMemoryLimit = useSelector(
|
||||
(state: AppState) =>
|
||||
state.tenants.createTenant.fields.tenantSize.resourcesMemoryLimit
|
||||
state.createTenant.fields.tenantSize.resourcesMemoryLimit
|
||||
);
|
||||
|
||||
// Common
|
||||
|
||||
1102
portal-ui/src/screens/Console/Tenants/AddTenant/createTenantSlice.ts
Normal file
1102
portal-ui/src/screens/Console/Tenants/AddTenant/createTenantSlice.ts
Normal file
File diff suppressed because it is too large
Load Diff
@@ -325,13 +325,12 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
<SelectWrapper
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
const newKey = e.target.value as string;
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
|
||||
arrCp[i].key = e.target.value as string;
|
||||
arrCp[i].value = keyValueMap[newKey][0];
|
||||
const newLKP: LabelKeyPair = {
|
||||
key: newKey,
|
||||
value: keyValueMap[newKey][0],
|
||||
};
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = newLKP;
|
||||
dispatch(setPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
id="select-access-policy"
|
||||
@@ -348,11 +347,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
name={`nodeselector-${i.toString()}`}
|
||||
value={kvp.key}
|
||||
onChange={(e) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].key = e.target.value;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
index={i}
|
||||
@@ -364,11 +363,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
{keyOptions.length > 0 && (
|
||||
<SelectWrapper
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].value = e.target.value as string;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
id="select-access-policy"
|
||||
@@ -391,11 +390,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
name={`nodeselector-${i.toString()}`}
|
||||
value={kvp.value}
|
||||
onChange={(e) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].value = e.target.value;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
index={i}
|
||||
@@ -408,7 +407,7 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
const arrCp = Object.assign([], keyValuePairs);
|
||||
const arrCp = [...keyValuePairs];
|
||||
if (keyOptions.length > 0) {
|
||||
arrCp.push({
|
||||
key: keyOptions[0].value,
|
||||
|
||||
@@ -322,13 +322,12 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
<SelectWrapper
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
const newKey = e.target.value as string;
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
|
||||
arrCp[i].key = e.target.value as string;
|
||||
arrCp[i].value = keyValueMap[newKey][0];
|
||||
const newLKP: LabelKeyPair = {
|
||||
key: newKey,
|
||||
value: keyValueMap[newKey][0],
|
||||
};
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = newLKP;
|
||||
dispatch(setEditPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
id="select-access-policy"
|
||||
@@ -345,11 +344,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
name={`nodeselector-${i.toString()}`}
|
||||
value={kvp.key}
|
||||
onChange={(e) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].key = e.target.value;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setEditPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
index={i}
|
||||
@@ -361,11 +360,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
{keyOptions.length > 0 && (
|
||||
<SelectWrapper
|
||||
onChange={(e: SelectChangeEvent<string>) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].value = e.target.value as string;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setEditPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
id="select-access-policy"
|
||||
@@ -388,11 +387,11 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
name={`nodeselector-${i.toString()}`}
|
||||
value={kvp.value}
|
||||
onChange={(e) => {
|
||||
const arrCp: LabelKeyPair[] = Object.assign(
|
||||
[],
|
||||
keyValuePairs
|
||||
);
|
||||
arrCp[i].value = e.target.value;
|
||||
const arrCp: LabelKeyPair[] = [...keyValuePairs];
|
||||
arrCp[i] = {
|
||||
key: arrCp[i].key,
|
||||
value: e.target.value as string,
|
||||
};
|
||||
dispatch(setEditPoolKeyValuePairs(arrCp));
|
||||
}}
|
||||
index={i}
|
||||
@@ -405,7 +404,7 @@ const Affinity = ({ classes }: IAffinityProps) => {
|
||||
<IconButton
|
||||
size={"small"}
|
||||
onClick={() => {
|
||||
const arrCp = Object.assign([], keyValuePairs);
|
||||
const arrCp = [...keyValuePairs];
|
||||
if (keyOptions.length > 0) {
|
||||
arrCp.push({
|
||||
key: keyOptions[0].value,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -26,100 +26,6 @@ import { IResourcesSize, ITenant } from "./ListTenants/types";
|
||||
import { KeyPair, Opts } from "./ListTenants/utils";
|
||||
import { IntegrationConfiguration } from "./AddTenant/Steps/TenantResources/utils";
|
||||
|
||||
export const ADD_TENANT_SET_CURRENT_PAGE = "ADD_TENANT/SET_CURRENT_PAGE";
|
||||
export const ADD_TENANT_UPDATE_FIELD = "ADD_TENANT/UPDATE_FIELD";
|
||||
export const ADD_TENANT_SET_PAGE_VALID = "ADD_TENANT/SET_PAGE_VALID";
|
||||
export const ADD_TENANT_RESET_FORM = "ADD_TENANT/RESET_FORM";
|
||||
|
||||
// Name Tenant
|
||||
export const ADD_TENANT_SET_STORAGE_CLASSES_LIST =
|
||||
"ADD_TENANT/SET_STORAGE_CLASSES_LIST";
|
||||
export const ADD_TENANT_SET_LIMIT_SIZE = "ADD_TENANT/SET_LIMIT_SIZE";
|
||||
export const ADD_TENANT_SET_STORAGE_TYPE =
|
||||
"ADD_TENANT/ADD_TENANT_SET_STORAGE_TYPE";
|
||||
|
||||
// Configuration
|
||||
export const ADD_TENANT_ADD_MINIO_DOMAIN = "ADD_TENANT/ADD_MINIO_DOMAIN";
|
||||
export const ADD_TENANT_DELETE_MINIO_DOMAIN = "ADD_TENANT/DELETE_MINIO_DOMAIN";
|
||||
|
||||
// Security
|
||||
export const ADD_TENANT_ADD_MINIO_KEYPAIR = "ADD_TENANT/ADD_MINIO_KEYPAIR";
|
||||
export const ADD_TENANT_ADD_FILE_TO_MINIO_KEYPAIR =
|
||||
"ADD_TENANT/ADD_FILE_MINIO_KEYPAIR";
|
||||
export const ADD_TENANT_DELETE_MINIO_KEYPAIR =
|
||||
"ADD_TENANT/DELETE_MINIO_KEYPAIR";
|
||||
export const ADD_TENANT_ADD_CA_KEYPAIR = "ADD_TENANT/ADD_CA_KEYPAIR";
|
||||
export const ADD_TENANT_ADD_FILE_TO_CA_KEYPAIR =
|
||||
"ADD_TENANT/ADD_FILE_TO_CA_KEYPAIR";
|
||||
export const ADD_TENANT_DELETE_CA_KEYPAIR = "ADD_TENANT/DELETE_CA_KEYPAIR";
|
||||
export const ADD_TENANT_ADD_CONSOLE_CERT = "ADD_TENANT/ADD_CONSOLE_CERT";
|
||||
export const ADD_TENANT_ADD_CONSOLE_CA_KEYPAIR =
|
||||
"ADD_TENANT/ADD_CONSOLE_CA_KEYPAIR";
|
||||
export const ADD_TENANT_ADD_FILE_TO_CONSOLE_CA_KEYPAIR =
|
||||
"ADD_TENANT/ADD_FILE_TO_CONSOLE_CA_KEYPAIR";
|
||||
export const ADD_TENANT_DELETE_CONSOLE_CA_KEYPAIR =
|
||||
"ADD_TENANT/DELETE_CONSOLE_CA_KEYPAIR";
|
||||
|
||||
// Encryption
|
||||
export const ADD_TENANT_ENCRYPTION_SERVER_CERT =
|
||||
"ADD_TENANT/ENCRYPTION_SERVER_CERT";
|
||||
export const ADD_TENANT_ENCRYPTION_CLIENT_CERT =
|
||||
"ADD_TENANT/ENCRYPTION_CLIENT_CERT";
|
||||
export const ADD_TENANT_ENCRYPTION_VAULT_CERT =
|
||||
"ADD_TENANT/ENCRYPTION_VAULT_CERT";
|
||||
export const ADD_TENANT_ENCRYPTION_VAULT_CA = "ADD_TENANT/ENCRYPTION_VAULT_CA";
|
||||
export const ADD_TENANT_ENCRYPTION_GEMALTO_CA =
|
||||
"ADD_TENANT/ENCRYPTION_GEMALTO_CA";
|
||||
|
||||
// Affinity Node Selector KeyPairs
|
||||
export const ADD_TENANT_SET_KEY_PAIR_VALUE = "ADD_TENANT/SET_KEY_PAIR_VALUE";
|
||||
|
||||
// Affinity Tolerations
|
||||
export const ADD_TENANT_SET_TOLERATION_VALUE =
|
||||
"ADD_TENANT/SET_TOLERATION_VALUE";
|
||||
export const ADD_TENANT_ADD_NEW_TOLERATION = "ADD_TENANT/ADD_NEW_TOLERATION";
|
||||
export const ADD_TENANT_REMOVE_TOLERATION_ROW =
|
||||
"ADD_TENANT/REMOVE_TOLERATION_ROW";
|
||||
|
||||
// Tenant Details
|
||||
export const TENANT_DETAILS_SET_LOADING = "TENANT_DETAILS/SET_LOADING";
|
||||
export const TENANT_DETAILS_SET_CURRENT_TENANT =
|
||||
"TENANT_DETAILS/SET_CURRENT_TENANT";
|
||||
export const TENANT_DETAILS_SET_TENANT = "TENANT_DETAILS/SET_TENANT";
|
||||
export const TENANT_DETAILS_SET_TAB = "TENANT_DETAILS/SET_TAB";
|
||||
|
||||
// Add Pool
|
||||
export const ADD_POOL_SET_POOL_STORAGE_CLASSES =
|
||||
"ADD_POOL/SET_POOL_STORAGE_CLASSES";
|
||||
export const ADD_POOL_SET_PAGE_VALID = "ADD_POOL/SET_PAGE_VALID";
|
||||
export const ADD_POOL_SET_VALUE = "ADD_POOL/SET_VALUE";
|
||||
export const ADD_POOL_SET_LOADING = "ADD_POOL/SET_LOADING";
|
||||
export const ADD_POOL_RESET_FORM = "ADD_POOL/RESET_FORM";
|
||||
export const ADD_POOL_SET_KEY_PAIR_VALUE = "ADD_POOL/SET_KEY_PAIR_VALUE";
|
||||
|
||||
// Pool Tolerations
|
||||
export const ADD_POOL_SET_TOLERATION_VALUE = "ADD_POOL/SET_TOLERATION_VALUE";
|
||||
export const ADD_POOL_ADD_NEW_TOLERATION = "ADD_POOL/ADD_NEW_TOLERATION";
|
||||
export const ADD_POOL_REMOVE_TOLERATION_ROW = "ADD_POOL/REMOVE_TOLERATION_ROW";
|
||||
|
||||
// Pool Details
|
||||
export const POOL_DETAILS_SET_OPEN_DETAILS = "POOL_DETAILS/SET_OPEN_DETAILS";
|
||||
export const POOL_DETAILS_SET_SELECTED_POOL = "POOL_DETAILS/SET_SELECTED_POOL";
|
||||
|
||||
// Edit Pool
|
||||
export const EDIT_POOL_SET_INITIAL_INFO = "EDIT_POOL/SET_INITIAL_INFO";
|
||||
export const EDIT_POOL_SET_POOL_STORAGE_CLASSES =
|
||||
"EDIT_POOL/SET_POOL_STORAGE_CLASSES";
|
||||
export const EDIT_POOL_SET_PAGE_VALID = "EDIT_POOL/SET_PAGE_VALID";
|
||||
export const EDIT_POOL_SET_VALUE = "EDIT_POOL/SET_VALUE";
|
||||
export const EDIT_POOL_SET_LOADING = "EDIT_POOL/SET_LOADING";
|
||||
export const EDIT_POOL_RESET_FORM = "EDIT_POOL/RESET_FORM";
|
||||
export const EDIT_POOL_SET_KEY_PAIR_VALUE = "EDIT_POOL/SET_KEY_PAIR_VALUE";
|
||||
export const EDIT_POOL_SET_TOLERATION_VALUE = "EDIT_POOL/SET_TOLERATION_VALUE";
|
||||
export const EDIT_POOL_ADD_NEW_TOLERATION = "EDIT_POOL/ADD_NEW_TOLERATION";
|
||||
export const EDIT_POOL_REMOVE_TOLERATION_ROW =
|
||||
"EDIT_POOL/REMOVE_TOLERATION_ROW";
|
||||
|
||||
export interface ICertificateInfo {
|
||||
name: string;
|
||||
serialNumber: string;
|
||||
@@ -192,17 +98,6 @@ export interface ITenantEncryptionResponse {
|
||||
azure?: IAzureConfig;
|
||||
}
|
||||
|
||||
export interface ICreateTenant {
|
||||
page: number;
|
||||
validPages: string[];
|
||||
storageClasses: Opts[];
|
||||
limitSize: any;
|
||||
fields: IFieldStore;
|
||||
certificates: ICertificatesItems;
|
||||
nodeSelectorPairs: LabelKeyPair[];
|
||||
tolerations: ITolerationModel[];
|
||||
}
|
||||
|
||||
export interface ICertificatesItems {
|
||||
minioCertificates: KeyPair[];
|
||||
caCertificates: KeyPair[];
|
||||
@@ -394,7 +289,6 @@ export interface ITenantDetails {
|
||||
}
|
||||
|
||||
export interface ITenantState {
|
||||
createTenant: ICreateTenant;
|
||||
tenantDetails: ITenantDetails;
|
||||
addPool: IAddPool;
|
||||
editPool: IEditPool;
|
||||
|
||||
@@ -38,10 +38,9 @@ import {
|
||||
performDownload,
|
||||
} from "../../../common/utils";
|
||||
import DistributedOnly from "../Common/DistributedOnly/DistributedOnly";
|
||||
import { AppState } from "../../../store";
|
||||
import { InspectMenuIcon } from "../../../icons/SidebarMenus";
|
||||
import KeyRevealer from "./KeyRevealer";
|
||||
import { setErrorSnackMessage } from "../../../systemSlice";
|
||||
import { selDistSet, setErrorSnackMessage } from "../../../systemSlice";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -93,9 +92,7 @@ const ExampleBlock = ({
|
||||
|
||||
const Inspect = ({ classes }: { classes: any }) => {
|
||||
const dispatch = useDispatch();
|
||||
const distributedSetup = useSelector(
|
||||
(state: AppState) => state.system.distributedSetup
|
||||
);
|
||||
const distributedSetup = useSelector(selDistSet);
|
||||
const [volumeName, setVolumeName] = useState<string>("");
|
||||
const [inspectPath, setInspectPath] = useState<string>("");
|
||||
const [isEncrypt, setIsEncrypt] = useState<boolean>(true);
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
import React, { Fragment } from "react";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import Grid from "@mui/material/Grid";
|
||||
|
||||
import {
|
||||
@@ -44,15 +43,9 @@ import {
|
||||
IAM_PAGES_PERMISSIONS,
|
||||
} from "../../../../common/SecureComponent/permissions";
|
||||
import { hasPermission } from "../../../../common/SecureComponent";
|
||||
import { AppState } from "../../../../store";
|
||||
import { connect } from "react-redux";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
|
||||
interface IConfigurationOptions {
|
||||
classes: any;
|
||||
features: string[];
|
||||
}
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
settingsOptionsContainer: {
|
||||
display: "flex" as const,
|
||||
@@ -67,9 +60,11 @@ const styles = (theme: Theme) =>
|
||||
...searchField,
|
||||
...actionsTray,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const ToolsList = ({ classes, features }: IConfigurationOptions) => {
|
||||
const ToolsList = () => {
|
||||
const classes = useStyles();
|
||||
const configurationElements: IElement[] = [
|
||||
{
|
||||
icon: <LogsIcon />,
|
||||
@@ -159,10 +154,4 @@ const ToolsList = ({ classes, features }: IConfigurationOptions) => {
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
features: state.console.session.features,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, null);
|
||||
|
||||
export default connector(withStyles(styles)(ToolsList));
|
||||
export default ToolsList;
|
||||
|
||||
@@ -24,12 +24,11 @@ import {
|
||||
TextField,
|
||||
} from "@mui/material";
|
||||
import { IMessageEvent, w3cwebsocket as W3CWebSocket } from "websocket";
|
||||
import { connect } from "react-redux";
|
||||
import { useDispatch, useSelector } from "react-redux";
|
||||
import { Theme } from "@mui/material/styles";
|
||||
import createStyles from "@mui/styles/createStyles";
|
||||
import withStyles from "@mui/styles/withStyles";
|
||||
import { AppState } from "../../../store";
|
||||
import { watchMessageReceived, watchResetMessages } from "./actions";
|
||||
import { Bucket, BucketList, EventInfo } from "./types";
|
||||
import { niceBytes, timeFromDate } from "../../../common/utils";
|
||||
import { wsProtocol } from "../../../utils/wsUtils";
|
||||
@@ -44,8 +43,10 @@ import TableWrapper from "../Common/TableWrapper/TableWrapper";
|
||||
import PageHeader from "../Common/PageHeader/PageHeader";
|
||||
import api from "../../../common/api";
|
||||
import PageLayout from "../Common/Layout/PageLayout";
|
||||
import makeStyles from "@mui/styles/makeStyles";
|
||||
import { watchMessageReceived, watchResetMessages } from "./watchSlice";
|
||||
|
||||
const styles = (theme: Theme) =>
|
||||
const useStyles = makeStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
searchPrefix: {
|
||||
flexGrow: 1,
|
||||
@@ -62,7 +63,8 @@ const styles = (theme: Theme) =>
|
||||
...actionsTray,
|
||||
...searchField,
|
||||
...containerForHeader(theme.spacing(4)),
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
const SelectStyled = withStyles((theme: Theme) =>
|
||||
createStyles({
|
||||
@@ -83,19 +85,12 @@ const SelectStyled = withStyles((theme: Theme) =>
|
||||
})
|
||||
)(InputBase);
|
||||
|
||||
interface IWatch {
|
||||
classes: any;
|
||||
watchMessageReceived: typeof watchMessageReceived;
|
||||
watchResetMessages: typeof watchResetMessages;
|
||||
messages: EventInfo[];
|
||||
}
|
||||
const Watch = () => {
|
||||
const dispatch = useDispatch();
|
||||
const classes = useStyles();
|
||||
|
||||
const messages = useSelector((state: AppState) => state.watch.messages);
|
||||
|
||||
const Watch = ({
|
||||
classes,
|
||||
watchMessageReceived,
|
||||
watchResetMessages,
|
||||
messages,
|
||||
}: IWatch) => {
|
||||
const [start, setStart] = useState(false);
|
||||
const [bucketName, setBucketName] = useState("Select Bucket");
|
||||
const [prefix, setPrefix] = useState("");
|
||||
@@ -121,7 +116,7 @@ const Watch = ({
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
watchResetMessages();
|
||||
dispatch(watchResetMessages());
|
||||
// begin watch if bucketName in bucketList and start pressed
|
||||
if (start && bucketList.some((bucket) => bucket.name === bucketName)) {
|
||||
const url = new URL(window.location.toString());
|
||||
@@ -150,7 +145,7 @@ const Watch = ({
|
||||
let m: EventInfo = JSON.parse(message.data.toString());
|
||||
m.Time = new Date(m.Time.toString());
|
||||
m.key = Math.random();
|
||||
watchMessageReceived(m);
|
||||
dispatch(watchMessageReceived(m));
|
||||
};
|
||||
c.onclose = () => {
|
||||
clearInterval(interval);
|
||||
@@ -169,15 +164,7 @@ const Watch = ({
|
||||
// reset start status
|
||||
setStart(false);
|
||||
}
|
||||
}, [
|
||||
watchMessageReceived,
|
||||
start,
|
||||
bucketList,
|
||||
bucketName,
|
||||
prefix,
|
||||
suffix,
|
||||
watchResetMessages,
|
||||
]);
|
||||
}, [dispatch, start, bucketList, bucketName, prefix, suffix]);
|
||||
|
||||
const bucketNames = bucketList.map((bucketName) => ({
|
||||
label: bucketName.name,
|
||||
@@ -296,13 +283,4 @@ const Watch = ({
|
||||
);
|
||||
};
|
||||
|
||||
const mapState = (state: AppState) => ({
|
||||
messages: state.watch.messages,
|
||||
});
|
||||
|
||||
const connector = connect(mapState, {
|
||||
watchMessageReceived: watchMessageReceived,
|
||||
watchResetMessages: watchResetMessages,
|
||||
});
|
||||
|
||||
export default connector(withStyles(styles)(Watch));
|
||||
export default Watch;
|
||||
|
||||
@@ -1,46 +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 { EventInfo } from "./types";
|
||||
|
||||
export const WATCH_MESSAGE_RECEIVED = "WATCH_MESSAGE_RECEIVED";
|
||||
export const WATCH_RESET_MESSAGES = "WATCH_RESET_MESSAGES";
|
||||
|
||||
interface WatchMessageReceivedAction {
|
||||
type: typeof WATCH_MESSAGE_RECEIVED;
|
||||
message: EventInfo;
|
||||
}
|
||||
|
||||
interface WatchResetMessagesAction {
|
||||
type: typeof WATCH_RESET_MESSAGES;
|
||||
}
|
||||
|
||||
export type WatchActionTypes =
|
||||
| WatchMessageReceivedAction
|
||||
| WatchResetMessagesAction;
|
||||
|
||||
export function watchMessageReceived(message: EventInfo) {
|
||||
return {
|
||||
type: WATCH_MESSAGE_RECEIVED,
|
||||
message: message,
|
||||
};
|
||||
}
|
||||
|
||||
export function watchResetMessages() {
|
||||
return {
|
||||
type: WATCH_RESET_MESSAGES,
|
||||
};
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// This file is part of MinIO Console Server
|
||||
// Copyright (c) 2021 MinIO, Inc.
|
||||
// Copyright (c) 2022 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
|
||||
@@ -14,11 +14,7 @@
|
||||
// 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 {
|
||||
WATCH_MESSAGE_RECEIVED,
|
||||
WATCH_RESET_MESSAGES,
|
||||
WatchActionTypes,
|
||||
} from "./actions";
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { EventInfo } from "./types";
|
||||
|
||||
export interface WatchState {
|
||||
@@ -29,22 +25,19 @@ const initialState: WatchState = {
|
||||
messages: [],
|
||||
};
|
||||
|
||||
export function watchReducer(
|
||||
state = initialState,
|
||||
action: WatchActionTypes
|
||||
): WatchState {
|
||||
switch (action.type) {
|
||||
case WATCH_MESSAGE_RECEIVED:
|
||||
return {
|
||||
...state,
|
||||
messages: [...state.messages, action.message],
|
||||
};
|
||||
case WATCH_RESET_MESSAGES:
|
||||
return {
|
||||
...state,
|
||||
messages: [],
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
}
|
||||
export const watchSlice = createSlice({
|
||||
name: "trace",
|
||||
initialState,
|
||||
reducers: {
|
||||
watchMessageReceived: (state, action: PayloadAction<EventInfo>) => {
|
||||
state.messages.push(action.payload);
|
||||
},
|
||||
watchResetMessages: (state) => {
|
||||
state.messages = [];
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { watchResetMessages, watchMessageReceived } = watchSlice.actions;
|
||||
|
||||
export default watchSlice.reducer;
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { ISessionResponse } from "./types";
|
||||
import { AppState } from "../../store";
|
||||
|
||||
export interface ConsoleState {
|
||||
session: ISessionResponse;
|
||||
@@ -46,5 +47,7 @@ export const consoleSlice = createSlice({
|
||||
});
|
||||
|
||||
export const { saveSessionResponse, resetSession } = consoleSlice.actions;
|
||||
export const selSession = (state: AppState) => state.console.session;
|
||||
export const selFeatures = (state: AppState) => state.console.session.features;
|
||||
|
||||
export default consoleSlice.reducer;
|
||||
|
||||
@@ -16,15 +16,17 @@
|
||||
|
||||
import systemReducer from "./systemSlice";
|
||||
import traceReducer from "./screens/Console/Trace/traceSlice";
|
||||
import { logReducer } from "./screens/Console/Logs/reducers";
|
||||
import logReducer from "./screens/Console/Logs/logsSlice";
|
||||
import healthInfoReducer from "./screens/Console/HealthInfo/healthInfoSlice";
|
||||
import { watchReducer } from "./screens/Console/Watch/reducers";
|
||||
import watchReducer from "./screens/Console/Watch/watchSlice";
|
||||
import consoleReducer from "./screens/Console/consoleSlice";
|
||||
import bucketsReducer from "./screens/Console/Buckets/bucketsSlice";
|
||||
import bucketDetailsReducer from "./screens/Console/Buckets/BucketDetails/bucketDetailsSlice";
|
||||
import objectBrowserReducer from "./screens/Console/ObjectBrowser/objectBrowserSlice";
|
||||
import tenantsReducer from "./screens/Console/Tenants/tenantsSlice";
|
||||
import dashboardReducer from "./screens/Console/Dashboard/dashboardSlice";
|
||||
import { configureStore } from "@reduxjs/toolkit";
|
||||
import createTenantReducer from "./screens/Console/Tenants/AddTenant/createTenantSlice";
|
||||
|
||||
export const store = configureStore({
|
||||
reducer: {
|
||||
@@ -34,10 +36,13 @@ export const store = configureStore({
|
||||
watch: watchReducer,
|
||||
console: consoleReducer,
|
||||
buckets: bucketsReducer,
|
||||
bucketDetails: bucketDetailsReducer,
|
||||
objectBrowser: objectBrowserReducer,
|
||||
healthInfo: healthInfoReducer,
|
||||
tenants: tenantsReducer,
|
||||
dashboard: dashboardReducer,
|
||||
// Operator Reducers
|
||||
tenants: tenantsReducer,
|
||||
createTenant: createTenantReducer,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { snackBarMessage, SRInfoStateType } from "./types";
|
||||
import { ErrorResponseHandler } from "./common/types";
|
||||
import { AppState } from "./store";
|
||||
|
||||
// determine whether we have the sidebar state stored on localstorage
|
||||
const initSideBarOpen = localStorage.getItem("sidebarOpen")
|
||||
@@ -154,4 +155,8 @@ export const {
|
||||
setSiteReplicationInfo,
|
||||
} = systemSlice.actions;
|
||||
|
||||
export const selDistSet = (state: AppState) => state.system.distributedSetup;
|
||||
export const selSiteRep = (state: AppState) => state.system.siteReplicationInfo;
|
||||
export const selOpMode = (state: AppState) => state.system.operatorMode;
|
||||
|
||||
export default systemSlice.reducer;
|
||||
|
||||
@@ -134,10 +134,10 @@ func serveWS(w http.ResponseWriter, req *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
//// DELETE ME !!!
|
||||
// Un-comment for development so websockets work on port 5005
|
||||
// upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||
// return true
|
||||
//}
|
||||
// return true
|
||||
// }
|
||||
|
||||
// upgrades the HTTP server connection to the WebSocket protocol.
|
||||
conn, err := upgrader.Upgrade(w, req, nil)
|
||||
|
||||
Reference in New Issue
Block a user