Service account ux (#1229)
Co-authored-by: Daniel Valdivia <18384552+dvaldivia@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
373bfbfe3f
commit
70a4d76283
81
portal-ui/src/icons/NewAccountIcon.tsx
Normal file
81
portal-ui/src/icons/NewAccountIcon.tsx
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
// This file is part of MinIO Console Server
|
||||||
|
// Copyright (c) 2021 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { SvgIcon } from "@mui/material";
|
||||||
|
const NewAccountIcon = () => {
|
||||||
|
return (
|
||||||
|
<SvgIcon>
|
||||||
|
<svg
|
||||||
|
id="Account_Icon"
|
||||||
|
data-name="Account Icon"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 16.409 13.096"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
id="Trazado_391"
|
||||||
|
data-name="Trazado 391"
|
||||||
|
d="M-4332.855-1143.481a3.023,3.023,0,0,0,2.958-3.078,3.023,3.023,0,0,0-2.958-3.078,3.023,3.023,0,0,0-2.958,3.078A3.023,3.023,0,0,0-4332.855-1143.481Zm0-5.194a2.078,2.078,0,0,1,2.03,2.116,2.077,2.077,0,0,1-2.03,2.116,2.075,2.075,0,0,1-2.028-2.116A2.076,2.076,0,0,1-4332.855-1148.675Z"
|
||||||
|
transform="translate(4339.12 1149.637)"
|
||||||
|
fill="#07193e"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Trazado_392"
|
||||||
|
data-name="Trazado 392"
|
||||||
|
d="M-4337.952-1130.053a1.374,1.374,0,0,0,1.252.775h4.993a1.354,1.354,0,0,0,1.25-.786,1.675,1.675,0,0,0-.164-1.686,4.521,4.521,0,0,0-1.7-1.405,4.361,4.361,0,0,0-2.125-.438,4.483,4.483,0,0,0-3.318,1.808c-.026.035-.051.071-.075.106A1.641,1.641,0,0,0-4337.952-1130.053Zm6.663-.437a.426.426,0,0,1-.417.25h-4.993a.453.453,0,0,1-.427-.254.64.64,0,0,1,.053-.632h0c.017-.027.037-.054.057-.08a3.539,3.539,0,0,1,2.622-1.424c.056,0,.113,0,.168,0a3.606,3.606,0,0,1,2.864,1.466A.686.686,0,0,1-4331.29-1130.49Z"
|
||||||
|
transform="translate(4340.467 1140.236)"
|
||||||
|
fill="#07193e"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
id="Trazado_393"
|
||||||
|
data-name="Trazado 393"
|
||||||
|
d="M-4329.387-1146.951h-3.506a.476.476,0,0,0-.477.476.477.477,0,0,0,.477.476h3.506a1.047,1.047,0,0,1,1.046,1.045v7.99a1.047,1.047,0,0,1-1.046,1.045H-4341.8a1.047,1.047,0,0,1-1.046-1.045v-7.99A1.048,1.048,0,0,1-4341.8-1146a.476.476,0,0,0,.476-.476.476.476,0,0,0-.476-.476,2,2,0,0,0-2,2v7.99a2,2,0,0,0,2,2h12.412a2,2,0,0,0,2-2v-7.99A2,2,0,0,0-4329.387-1146.951Z"
|
||||||
|
transform="translate(4343.797 1148.063)"
|
||||||
|
fill="#07193e"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="Rectángulo_809"
|
||||||
|
data-name="Rectángulo 809"
|
||||||
|
width="3.266"
|
||||||
|
height="2.781"
|
||||||
|
rx="1.024"
|
||||||
|
transform="translate(11.002 3.376)"
|
||||||
|
fill="#07193e"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="Rectángulo_810"
|
||||||
|
data-name="Rectángulo 810"
|
||||||
|
width="3.266"
|
||||||
|
height="1.336"
|
||||||
|
rx="0.668"
|
||||||
|
transform="translate(11.002 7.328)"
|
||||||
|
fill="#07193e"
|
||||||
|
/>
|
||||||
|
<rect
|
||||||
|
id="Rectángulo_811"
|
||||||
|
data-name="Rectángulo 811"
|
||||||
|
width="3.266"
|
||||||
|
height="1.336"
|
||||||
|
rx="0.668"
|
||||||
|
transform="translate(11.002 9.621)"
|
||||||
|
fill="#07193e"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</SvgIcon>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NewAccountIcon;
|
||||||
35
portal-ui/src/icons/WarnIcon.tsx
Normal file
35
portal-ui/src/icons/WarnIcon.tsx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
// This file is part of MinIO Console Server
|
||||||
|
// Copyright (c) 2021 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
const WarnIcon = () => {
|
||||||
|
return (
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
|
||||||
|
<circle
|
||||||
|
cx="8"
|
||||||
|
cy="8"
|
||||||
|
r="7"
|
||||||
|
fill="none"
|
||||||
|
stroke="#e04006"
|
||||||
|
stroke-width="2"
|
||||||
|
/>
|
||||||
|
<path fill="none" stroke="#e04006" stroke-width="2" d="M8 4v6m0 1v2" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WarnIcon;
|
||||||
@@ -21,7 +21,10 @@ import { Button, LinearProgress } from "@mui/material";
|
|||||||
import { Theme } from "@mui/material/styles";
|
import { Theme } from "@mui/material/styles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import withStyles from "@mui/styles/withStyles";
|
import withStyles from "@mui/styles/withStyles";
|
||||||
import { modalBasic } from "../Common/FormComponents/common/styleLibrary";
|
import {
|
||||||
|
modalBasic,
|
||||||
|
serviceAccountStyles,
|
||||||
|
} from "../Common/FormComponents/common/styleLibrary";
|
||||||
import { NewServiceAccount } from "../Common/CredentialsPrompt/types";
|
import { NewServiceAccount } from "../Common/CredentialsPrompt/types";
|
||||||
import { setModalErrorSnackMessage } from "../../../actions";
|
import { setModalErrorSnackMessage } from "../../../actions";
|
||||||
import { ErrorResponseHandler } from "../../../common/types";
|
import { ErrorResponseHandler } from "../../../common/types";
|
||||||
@@ -33,26 +36,7 @@ import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWr
|
|||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
jsonPolicyEditor: {
|
...serviceAccountStyles,
|
||||||
minHeight: 400,
|
|
||||||
width: "100%",
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
textAlign: "right",
|
|
||||||
},
|
|
||||||
infoDetails: {
|
|
||||||
color: "#393939",
|
|
||||||
fontSize: 12,
|
|
||||||
fontStyle: "italic",
|
|
||||||
marginBottom: "8px",
|
|
||||||
},
|
|
||||||
containerScrollable: {
|
|
||||||
maxHeight: "calc(100vh - 300px)" as const,
|
|
||||||
overflowY: "auto" as const,
|
|
||||||
},
|
|
||||||
codeMirrorContainer: {
|
|
||||||
marginBottom: 20,
|
|
||||||
},
|
|
||||||
...modalBasic,
|
...modalBasic,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -157,72 +141,82 @@ const AddServiceAccount = ({
|
|||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<FormSwitchWrapper
|
|
||||||
value="locking"
|
|
||||||
id="locking"
|
|
||||||
name="locking"
|
|
||||||
checked={isRestrictedByPolicy}
|
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setIsRestrictedByPolicy(event.target.checked);
|
|
||||||
}}
|
|
||||||
label={"Restrict with policy"}
|
|
||||||
/>
|
|
||||||
<FormSwitchWrapper
|
|
||||||
value="locking"
|
|
||||||
id="locking"
|
|
||||||
name="locking"
|
|
||||||
checked={addCredentials}
|
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setAddCredentials(event.target.checked);
|
|
||||||
}}
|
|
||||||
label={"Customize Credentials"}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
{isRestrictedByPolicy && (
|
|
||||||
<Grid item xs={12} className={classes.codeMirrorContainer}>
|
|
||||||
<CodeMirrorWrapper
|
|
||||||
value={policyDefinition}
|
|
||||||
onBeforeChange={(editor, data, value) => {
|
|
||||||
setPolicyDefinition(value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
{addCredentials && (
|
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<InputBoxWrapper
|
<FormSwitchWrapper
|
||||||
value={accessKey}
|
value="locking"
|
||||||
label={"Access Key"}
|
classes={classes}
|
||||||
id={"accessKey"}
|
id="locking"
|
||||||
name={"accessKey"}
|
name="locking"
|
||||||
placeholder={"Enter Access Key"}
|
checked={addCredentials}
|
||||||
onChange={(e) => {
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
setAccessKey(e.target.value);
|
setAddCredentials(event.target.checked);
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<InputBoxWrapper
|
|
||||||
value={secretKey}
|
|
||||||
label={"Secret Key"}
|
|
||||||
id={"secretKey"}
|
|
||||||
name={"secretKey"}
|
|
||||||
placeholder={"Enter Secret Key"}
|
|
||||||
onChange={(e) => {
|
|
||||||
setSecretKey(e.target.value);
|
|
||||||
}}
|
}}
|
||||||
|
label={"Customize Credentials"}
|
||||||
/>
|
/>
|
||||||
|
{addCredentials && (
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<div className={classes.stackedInputs}>
|
||||||
|
<InputBoxWrapper
|
||||||
|
value={accessKey}
|
||||||
|
label={"Access Key"}
|
||||||
|
id={"accessKey"}
|
||||||
|
name={"accessKey"}
|
||||||
|
placeholder={"Enter Access Key"}
|
||||||
|
onChange={(e) => {
|
||||||
|
setAccessKey(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<InputBoxWrapper
|
||||||
|
value={secretKey}
|
||||||
|
label={"Secret Key"}
|
||||||
|
id={"secretKey"}
|
||||||
|
name={"secretKey"}
|
||||||
|
placeholder={"Enter Secret Key"}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSecretKey(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
)}
|
<Grid item xs={12}>
|
||||||
|
<FormSwitchWrapper
|
||||||
|
value="locking"
|
||||||
|
id="locking"
|
||||||
|
name="locking"
|
||||||
|
classes={classes}
|
||||||
|
checked={isRestrictedByPolicy}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setIsRestrictedByPolicy(event.target.checked);
|
||||||
|
}}
|
||||||
|
label={"Restrict with policy"}
|
||||||
|
/>
|
||||||
|
{isRestrictedByPolicy && (
|
||||||
|
<Grid item xs={12} className={classes.codeMirrorContainer}>
|
||||||
|
<CodeMirrorWrapper
|
||||||
|
label={"Policy "}
|
||||||
|
value={policyDefinition}
|
||||||
|
onBeforeChange={(editor, data, value) => {
|
||||||
|
setPolicyDefinition(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={12} className={classes.buttonContainer}>
|
<Grid item xs={12} className={classes.buttonContainer}>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.clearButton}
|
variant="outlined"
|
||||||
|
className={classes.buttonSpacer}
|
||||||
onClick={resetForm}
|
onClick={resetForm}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
</button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// This file is part of MinIO Console Server
|
||||||
|
// Copyright (c) 2021 MinIO, Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import React from "react";
|
||||||
|
import { InputAdornment, OutlinedInput } from "@mui/material";
|
||||||
|
import BoxIconButton from "../BoxIconButton/BoxIconButton";
|
||||||
|
import withStyles from "@mui/styles/withStyles";
|
||||||
|
import { Theme } from "@mui/material/styles";
|
||||||
|
import createStyles from "@mui/styles/createStyles";
|
||||||
|
import CopyToClipboard from "react-copy-to-clipboard";
|
||||||
|
import { CopyIcon } from "../../../../icons";
|
||||||
|
|
||||||
|
const styles = (theme: Theme) =>
|
||||||
|
createStyles({
|
||||||
|
container: {
|
||||||
|
display: "flex",
|
||||||
|
flexFlow: "column",
|
||||||
|
padding: "20px 0 8px 0",
|
||||||
|
},
|
||||||
|
inputWithCopy: {
|
||||||
|
"& .MuiInputBase-root ": {
|
||||||
|
width: "100%",
|
||||||
|
background: "#FBFAFA",
|
||||||
|
"& .MuiInputBase-input": {
|
||||||
|
height: ".8rem",
|
||||||
|
},
|
||||||
|
"& .MuiInputAdornment-positionEnd": {
|
||||||
|
marginRight: ".5rem",
|
||||||
|
"& .MuiButtonBase-root": {
|
||||||
|
height: "2rem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"& .MuiButtonBase-root .MuiSvgIcon-root": {
|
||||||
|
fontSize: ".8rem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
inputLabel: {
|
||||||
|
fontSize: ".8rem",
|
||||||
|
fontWeight: 600,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const CredentialItem = ({
|
||||||
|
label = "",
|
||||||
|
value = "",
|
||||||
|
classes = {},
|
||||||
|
}: {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
classes: any;
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<div className={classes.container}>
|
||||||
|
<div className={classes.inputLabel}>{label}:</div>
|
||||||
|
<div className={classes.inputWithCopy}>
|
||||||
|
<OutlinedInput
|
||||||
|
value={value}
|
||||||
|
readOnly
|
||||||
|
endAdornment={
|
||||||
|
<InputAdornment position="end">
|
||||||
|
<CopyToClipboard text={value}>
|
||||||
|
<BoxIconButton
|
||||||
|
aria-label="copy"
|
||||||
|
tooltip={"Copy"}
|
||||||
|
onClick={() => {}}
|
||||||
|
onMouseDown={() => {}}
|
||||||
|
edge="end"
|
||||||
|
>
|
||||||
|
<CopyIcon />
|
||||||
|
</BoxIconButton>
|
||||||
|
</CopyToClipboard>
|
||||||
|
</InputAdornment>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default withStyles(styles)(CredentialItem);
|
||||||
@@ -21,22 +21,52 @@ import createStyles from "@mui/styles/createStyles";
|
|||||||
import withStyles from "@mui/styles/withStyles";
|
import withStyles from "@mui/styles/withStyles";
|
||||||
import { NewServiceAccount } from "./types";
|
import { NewServiceAccount } from "./types";
|
||||||
import { Button } from "@mui/material";
|
import { Button } from "@mui/material";
|
||||||
import Typography from "@mui/material/Typography";
|
|
||||||
import ModalWrapper from "../ModalWrapper/ModalWrapper";
|
import ModalWrapper from "../ModalWrapper/ModalWrapper";
|
||||||
import Grid from "@mui/material/Grid";
|
import Grid from "@mui/material/Grid";
|
||||||
|
import CredentialItem from "./CredentialItem";
|
||||||
|
import NewAccountIcon from "../../../../icons/NewAccountIcon";
|
||||||
|
import WarnIcon from "../../../../icons/WarnIcon";
|
||||||
|
import { DownloadIcon } from "../../../../icons";
|
||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
warningBlock: {
|
warningBlock: {
|
||||||
color: "red",
|
color: "red",
|
||||||
|
fontSize: ".85rem",
|
||||||
|
margin: ".5rem 0 .5rem 0",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
"& svg ": {
|
||||||
|
marginRight: ".3rem",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
credentialTitle: {
|
||||||
|
padding: ".8rem 0 0 0",
|
||||||
|
fontWeight: 600,
|
||||||
|
fontSize: ".9rem",
|
||||||
},
|
},
|
||||||
buttonContainer: {
|
buttonContainer: {
|
||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
|
marginTop: "1rem",
|
||||||
},
|
},
|
||||||
credentialsPanel: {
|
credentialsPanel: {
|
||||||
overflowY: "auto",
|
overflowY: "auto",
|
||||||
maxHeight: 350,
|
maxHeight: 350,
|
||||||
},
|
},
|
||||||
|
promptTitle: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
},
|
||||||
|
buttonSpacer: {
|
||||||
|
marginRight: ".9rem",
|
||||||
|
},
|
||||||
|
promptIcon: {
|
||||||
|
marginRight: ".1rem",
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
height: "2rem",
|
||||||
|
width: "2rem",
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
interface ICredentialsPromptProps {
|
interface ICredentialsPromptProps {
|
||||||
@@ -83,115 +113,125 @@ const CredentialsPrompt = ({
|
|||||||
onClose={() => {
|
onClose={() => {
|
||||||
closeModal();
|
closeModal();
|
||||||
}}
|
}}
|
||||||
title={`New ${entity} Created`}
|
title={
|
||||||
|
<div className={classes.promptTitle}>
|
||||||
|
<div className={classes.promptIcon}>
|
||||||
|
<NewAccountIcon />
|
||||||
|
</div>{" "}
|
||||||
|
<div>New {entity} Created</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
>
|
>
|
||||||
<React.Fragment>
|
<Grid container>
|
||||||
<Grid container>
|
<Grid item xs={12} className={classes.formScrollable}>
|
||||||
<Grid item xs={12} className={classes.formScrollable}>
|
A new {entity} has been created with the following details:
|
||||||
A new {entity} has been created with the following details:
|
{!idp && consoleCreds && (
|
||||||
{!idp && consoleCreds && (
|
<React.Fragment>
|
||||||
<React.Fragment>
|
<Grid item xs={12} className={classes.credentialsPanel}>
|
||||||
<Grid item xs={12} className={classes.credentialsPanel}>
|
<div className={classes.credentialTitle}>
|
||||||
<strong>Console Credentials</strong>
|
Console Credentials
|
||||||
{Array.isArray(consoleCreds) &&
|
</div>
|
||||||
consoleCreds.map((credentialsPair, index) => {
|
{Array.isArray(consoleCreds) &&
|
||||||
return (
|
consoleCreds.map((credentialsPair, index) => {
|
||||||
<ul key={`creds-item-${index.toString()}`}>
|
return (
|
||||||
<li>
|
<>
|
||||||
<b>Access Key:</b> {credentialsPair.accessKey}
|
<CredentialItem
|
||||||
</li>
|
label="Access Key"
|
||||||
<li>
|
value={credentialsPair.accessKey}
|
||||||
<b>Secret Key:</b> {credentialsPair.secretKey}
|
/>
|
||||||
</li>
|
<CredentialItem
|
||||||
</ul>
|
label="Secret Key"
|
||||||
);
|
value={credentialsPair.secretKey}
|
||||||
})}
|
/>
|
||||||
{!Array.isArray(consoleCreds) && (
|
</>
|
||||||
<ul>
|
);
|
||||||
<li>
|
})}
|
||||||
<b>Access Key:</b> {consoleCreds.accessKey}
|
{!Array.isArray(consoleCreds) && (
|
||||||
</li>
|
<>
|
||||||
<li>
|
<CredentialItem
|
||||||
<b>Secret Key:</b> {consoleCreds.secretKey}
|
label="Access Key"
|
||||||
</li>
|
value={consoleCreds.accessKey}
|
||||||
</ul>
|
/>
|
||||||
)}
|
<CredentialItem
|
||||||
</Grid>
|
label="Secret Key"
|
||||||
</React.Fragment>
|
value={consoleCreds.secretKey}
|
||||||
)}
|
/>
|
||||||
{idp ? (
|
</>
|
||||||
<Typography
|
)}
|
||||||
component="p"
|
</Grid>
|
||||||
variant="body1"
|
</React.Fragment>
|
||||||
className={classes.warningBlock}
|
)}
|
||||||
>
|
{idp ? (
|
||||||
Please Login via the configured external identity provider.
|
<div className={classes.warningBlock}>
|
||||||
</Typography>
|
Please Login via the configured external identity provider.
|
||||||
) : (
|
</div>
|
||||||
<Typography
|
) : (
|
||||||
component="p"
|
<div className={classes.warningBlock}>
|
||||||
variant="body1"
|
<WarnIcon />
|
||||||
className={classes.warningBlock}
|
<span>
|
||||||
>
|
|
||||||
Write these down, as this is the only time the secret will be
|
Write these down, as this is the only time the secret will be
|
||||||
displayed.
|
displayed.
|
||||||
</Typography>
|
</span>
|
||||||
)}
|
</div>
|
||||||
</Grid>
|
)}
|
||||||
<Grid item xs={12} className={classes.buttonContainer}>
|
</Grid>
|
||||||
{!idp && (
|
<Grid item xs={12} className={classes.buttonContainer}>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
variant="outlined"
|
||||||
let consoleExtras = {};
|
className={classes.buttonSpacer}
|
||||||
|
onClick={() => {
|
||||||
|
closeModal();
|
||||||
|
}}
|
||||||
|
color="primary"
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</Button>
|
||||||
|
|
||||||
if (consoleCreds) {
|
{!idp && (
|
||||||
if (!Array.isArray(consoleCreds)) {
|
|
||||||
consoleExtras = {
|
|
||||||
console: [
|
|
||||||
{
|
|
||||||
access_key: consoleCreds.accessKey,
|
|
||||||
secret_key: consoleCreds.secretKey,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
const cCreds = consoleCreds.map((itemMap) => {
|
|
||||||
return {
|
|
||||||
access_key: itemMap.accessKey,
|
|
||||||
secret_key: itemMap.secretKey,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
consoleExtras = {
|
|
||||||
console: [...cCreds],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
download(
|
|
||||||
"credentials.json",
|
|
||||||
JSON.stringify({
|
|
||||||
...consoleExtras,
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
color="primary"
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
closeModal();
|
let consoleExtras = {};
|
||||||
|
|
||||||
|
if (consoleCreds) {
|
||||||
|
if (!Array.isArray(consoleCreds)) {
|
||||||
|
consoleExtras = {
|
||||||
|
console: [
|
||||||
|
{
|
||||||
|
access_key: consoleCreds.accessKey,
|
||||||
|
secret_key: consoleCreds.secretKey,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
const cCreds = consoleCreds.map((itemMap) => {
|
||||||
|
return {
|
||||||
|
access_key: itemMap.accessKey,
|
||||||
|
secret_key: itemMap.secretKey,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
consoleExtras = {
|
||||||
|
console: [...cCreds],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
download(
|
||||||
|
"credentials.json",
|
||||||
|
JSON.stringify({
|
||||||
|
...consoleExtras,
|
||||||
|
})
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
color="secondary"
|
endIcon={<DownloadIcon />}
|
||||||
autoFocus
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
>
|
>
|
||||||
Done
|
Download
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
)}
|
||||||
</Grid>
|
</Grid>
|
||||||
</React.Fragment>
|
</Grid>
|
||||||
</ModalWrapper>
|
</ModalWrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -253,7 +253,13 @@ const FormSwitchWrapper = ({
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<Grid item xs={12} sm={2} textAlign={"right"}>
|
<Grid
|
||||||
|
item
|
||||||
|
xs={12}
|
||||||
|
sm={2}
|
||||||
|
textAlign={"right"}
|
||||||
|
className={classes.switchContainer}
|
||||||
|
>
|
||||||
{switchComponent}
|
{switchComponent}
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|||||||
@@ -1011,3 +1011,51 @@ export const linkStyles = (color: string) => ({
|
|||||||
cursor: "pointer",
|
cursor: "pointer",
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const serviceAccountStyles: any = {
|
||||||
|
jsonPolicyEditor: {
|
||||||
|
minHeight: 400,
|
||||||
|
width: "100%",
|
||||||
|
},
|
||||||
|
buttonContainer: {
|
||||||
|
textAlign: "right",
|
||||||
|
},
|
||||||
|
infoDetails: {
|
||||||
|
color: "#393939",
|
||||||
|
fontSize: 12,
|
||||||
|
fontStyle: "italic",
|
||||||
|
marginBottom: "8px",
|
||||||
|
},
|
||||||
|
containerScrollable: {
|
||||||
|
maxHeight: "calc(100vh - 200px)" as const,
|
||||||
|
overflowY: "auto" as const,
|
||||||
|
},
|
||||||
|
codeMirrorContainer: {
|
||||||
|
marginBottom: 20,
|
||||||
|
paddingLeft: 15,
|
||||||
|
"&:nth-child(2) .MuiGrid-root:nth-child(3)": {
|
||||||
|
border: "1px solid #EAEAEA",
|
||||||
|
},
|
||||||
|
"& label": {
|
||||||
|
marginBottom: ".5rem",
|
||||||
|
},
|
||||||
|
"& label + div": {
|
||||||
|
display: "none",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
stackedInputs: {
|
||||||
|
display: "flex",
|
||||||
|
gap: 15,
|
||||||
|
paddingBottom: "1rem",
|
||||||
|
paddingLeft: "1rem",
|
||||||
|
flexFlow: "column",
|
||||||
|
},
|
||||||
|
buttonSpacer: {
|
||||||
|
marginRight: "1rem",
|
||||||
|
},
|
||||||
|
switchContainer: {
|
||||||
|
display: "flex",
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "flex-end",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ interface IModalProps {
|
|||||||
classes: any;
|
classes: any;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
modalOpen: boolean;
|
modalOpen: boolean;
|
||||||
title: string;
|
title: string | React.ReactNode;
|
||||||
children: any;
|
children: any;
|
||||||
wideLimit?: boolean;
|
wideLimit?: boolean;
|
||||||
modalSnackMessage?: snackBarMessage;
|
modalSnackMessage?: snackBarMessage;
|
||||||
@@ -56,8 +56,8 @@ const styles = (theme: Theme) =>
|
|||||||
textAlign: "right",
|
textAlign: "right",
|
||||||
},
|
},
|
||||||
closeButton: {
|
closeButton: {
|
||||||
width: 45,
|
height: 16,
|
||||||
height: 45,
|
width: 16,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
backgroundColor: "initial",
|
backgroundColor: "initial",
|
||||||
"&:hover": {
|
"&:hover": {
|
||||||
@@ -79,30 +79,28 @@ const styles = (theme: Theme) =>
|
|||||||
"&::before": {
|
"&::before": {
|
||||||
...baseCloseLine,
|
...baseCloseLine,
|
||||||
transform: "rotate(45deg)",
|
transform: "rotate(45deg)",
|
||||||
|
height: 12,
|
||||||
},
|
},
|
||||||
"&::after": {
|
"&::after": {
|
||||||
...baseCloseLine,
|
...baseCloseLine,
|
||||||
transform: "rotate(-45deg)",
|
transform: "rotate(-45deg)",
|
||||||
|
height: 12,
|
||||||
},
|
},
|
||||||
"&:hover::before, &:hover::after": {
|
"&:hover::before, &:hover::after": {
|
||||||
borderColor: "#9C9C9C",
|
borderColor: "#9C9C9C",
|
||||||
},
|
},
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
display: "block",
|
display: "block",
|
||||||
position: "relative",
|
position: "relative",
|
||||||
|
height: 12,
|
||||||
|
width: 12,
|
||||||
},
|
},
|
||||||
titleClass: {
|
titleClass: {
|
||||||
padding: "0px 50px 12px",
|
padding: "0px 50px 12px",
|
||||||
"& h2": {
|
fontSize: "1.2rem",
|
||||||
fontWeight: 600,
|
fontWeight: 600,
|
||||||
color: "#000",
|
overflow: "hidden",
|
||||||
fontSize: 22,
|
whiteSpace: "nowrap",
|
||||||
width: "100%",
|
textOverflow: "ellipsis",
|
||||||
overflow: "hidden",
|
|
||||||
whiteSpace: "nowrap",
|
|
||||||
textOverflow: "ellipsis",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
modalContent: {
|
modalContent: {
|
||||||
padding: "0 50px",
|
padding: "0 50px",
|
||||||
|
|||||||
@@ -21,7 +21,10 @@ import { Button, LinearProgress } from "@mui/material";
|
|||||||
import { Theme } from "@mui/material/styles";
|
import { Theme } from "@mui/material/styles";
|
||||||
import createStyles from "@mui/styles/createStyles";
|
import createStyles from "@mui/styles/createStyles";
|
||||||
import withStyles from "@mui/styles/withStyles";
|
import withStyles from "@mui/styles/withStyles";
|
||||||
import { modalBasic } from "../Common/FormComponents/common/styleLibrary";
|
import {
|
||||||
|
modalBasic,
|
||||||
|
serviceAccountStyles,
|
||||||
|
} from "../Common/FormComponents/common/styleLibrary";
|
||||||
import { NewServiceAccount } from "../Common/CredentialsPrompt/types";
|
import { NewServiceAccount } from "../Common/CredentialsPrompt/types";
|
||||||
import { setModalErrorSnackMessage } from "../../../actions";
|
import { setModalErrorSnackMessage } from "../../../actions";
|
||||||
import { ErrorResponseHandler } from "../../../common/types";
|
import { ErrorResponseHandler } from "../../../common/types";
|
||||||
@@ -33,23 +36,7 @@ import InputBoxWrapper from "../Common/FormComponents/InputBoxWrapper/InputBoxWr
|
|||||||
|
|
||||||
const styles = (theme: Theme) =>
|
const styles = (theme: Theme) =>
|
||||||
createStyles({
|
createStyles({
|
||||||
jsonPolicyEditor: {
|
...serviceAccountStyles,
|
||||||
minHeight: 400,
|
|
||||||
width: "100%",
|
|
||||||
},
|
|
||||||
buttonContainer: {
|
|
||||||
textAlign: "right",
|
|
||||||
},
|
|
||||||
infoDetails: {
|
|
||||||
color: "#393939",
|
|
||||||
fontSize: 12,
|
|
||||||
fontStyle: "italic",
|
|
||||||
marginBottom: "8px",
|
|
||||||
},
|
|
||||||
containerScrollable: {
|
|
||||||
maxHeight: "calc(100vh - 300px)" as const,
|
|
||||||
overflowY: "auto" as const,
|
|
||||||
},
|
|
||||||
...modalBasic,
|
...modalBasic,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -157,72 +144,84 @@ const AddUserServiceAccount = ({
|
|||||||
</div>
|
</div>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12}>
|
<Grid item xs={12}>
|
||||||
<FormSwitchWrapper
|
<Grid item xs={12}>
|
||||||
value="locking"
|
<FormSwitchWrapper
|
||||||
id="locking"
|
classes={classes}
|
||||||
name="locking"
|
value="locking"
|
||||||
checked={isRestrictedByPolicy}
|
id="locking"
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
name="locking"
|
||||||
setIsRestrictedByPolicy(event.target.checked);
|
checked={addCredentials}
|
||||||
}}
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
label={"Restrict with policy"}
|
setAddCredentials(event.target.checked);
|
||||||
/>
|
}}
|
||||||
<FormSwitchWrapper
|
label={"Customize Credentials"}
|
||||||
value="locking"
|
/>
|
||||||
id="locking"
|
|
||||||
name="locking"
|
{addCredentials && (
|
||||||
checked={addCredentials}
|
<Grid item xs={12}>
|
||||||
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
<div className={classes.stackedInputs}>
|
||||||
setAddCredentials(event.target.checked);
|
<InputBoxWrapper
|
||||||
}}
|
value={accessKey}
|
||||||
label={"Customize Credentials"}
|
label={"Access Key"}
|
||||||
/>
|
id={"accessKey"}
|
||||||
|
name={"accessKey"}
|
||||||
|
placeholder={"Enter Access Key"}
|
||||||
|
onChange={(e) => {
|
||||||
|
setAccessKey(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<InputBoxWrapper
|
||||||
|
value={secretKey}
|
||||||
|
label={"Secret Key"}
|
||||||
|
id={"secretKey"}
|
||||||
|
name={"secretKey"}
|
||||||
|
placeholder={"Enter Secret Key"}
|
||||||
|
onChange={(e) => {
|
||||||
|
setSecretKey(e.target.value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs={12}>
|
||||||
|
<FormSwitchWrapper
|
||||||
|
value="locking"
|
||||||
|
id="locking"
|
||||||
|
name="locking"
|
||||||
|
classes={classes}
|
||||||
|
checked={isRestrictedByPolicy}
|
||||||
|
onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setIsRestrictedByPolicy(event.target.checked);
|
||||||
|
}}
|
||||||
|
label={"Restrict with policy"}
|
||||||
|
/>
|
||||||
|
|
||||||
|
{isRestrictedByPolicy && (
|
||||||
|
<Grid item xs={12} className={classes.codeMirrorContainer}>
|
||||||
|
<CodeMirrorWrapper
|
||||||
|
label={"Policy "}
|
||||||
|
value={policyDefinition}
|
||||||
|
onBeforeChange={(editor, data, value) => {
|
||||||
|
setPolicyDefinition(value);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
)}
|
||||||
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
{isRestrictedByPolicy && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<CodeMirrorWrapper
|
|
||||||
value={policyDefinition}
|
|
||||||
onBeforeChange={(editor, data, value) => {
|
|
||||||
setPolicyDefinition(value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
{addCredentials && (
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<InputBoxWrapper
|
|
||||||
value={accessKey}
|
|
||||||
label={"Access Key"}
|
|
||||||
id={"accessKey"}
|
|
||||||
name={"accessKey"}
|
|
||||||
placeholder={"Enter Access Key"}
|
|
||||||
onChange={(e) => {
|
|
||||||
setAccessKey(e.target.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<InputBoxWrapper
|
|
||||||
value={secretKey}
|
|
||||||
label={"Secret Key"}
|
|
||||||
id={"secretKey"}
|
|
||||||
name={"secretKey"}
|
|
||||||
placeholder={"Enter Secret Key"}
|
|
||||||
onChange={(e) => {
|
|
||||||
setSecretKey(e.target.value);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
</Grid>
|
|
||||||
)}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs={12} className={classes.buttonContainer}>
|
<Grid item xs={12} className={classes.buttonContainer}>
|
||||||
<button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
color="primary"
|
color="primary"
|
||||||
className={classes.clearButton}
|
variant="outlined"
|
||||||
|
className={classes.buttonSpacer}
|
||||||
onClick={resetForm}
|
onClick={resetForm}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
</button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
|
|||||||
Reference in New Issue
Block a user