-
Larbi Gharib authored
Change-Id: I012d8d3daf1a1b33caad890c0c20afc6c6e75e97
Larbi Gharib authoredChange-Id: I012d8d3daf1a1b33caad890c0c20afc6c6e75e97
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
PasswordDialog.js 8.66 KiB
import React, { useEffect } from "react";
// @material-ui/core components
import { makeStyles } from "@material-ui/core/styles";
// core components
import Button from "components/CustomButtons/Button.js";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogContentText from "@material-ui/core/DialogContentText";
import DialogTitle from "@material-ui/core/DialogTitle";
import Grid from "@material-ui/core/Grid";
import InputAdornment from "@material-ui/core/InputAdornment";
import { Formik } from "formik";
import FormikField from "components/FormikField/FormikField";
import * as Yup from "yup";
import axios from "axios";
import configApiCall from "api.js";
import { api_path_put_update_user } from "globalUrls";
import VpnKeyIcon from "@material-ui/icons/VpnKey";
import RefreshIcon from "@material-ui/icons/Refresh";
import FileCopyIcon from "@material-ui/icons/FileCopy";
import VisibilityIcon from "@material-ui/icons/Visibility";
import VisibilityOffIcon from "@material-ui/icons/VisibilityOff";
import IconButton from "@material-ui/core/IconButton";
import { CopyToClipboard } from "react-copy-to-clipboard";
let generator = require("generate-password");
const styles = (theme) => ({
root: {
flexGrow: 1,
},
button: {
margin: theme.spacing(1),
},
actionButtons: {
display: "flex",
justifyContent: "space-between",
},
});
const useStyles = makeStyles(styles);
export default function PasswordDialog(props) {
const classes = useStyles();
const [copied, setCopied] = React.useState(false);
const [generated, setGenerated] = React.useState(false);
const [passwordVisible, setPasswordVisible] = React.useState(false);
const passwordGenerator = () => {
return generator.generate({
length: 10,
uppercase: false,
numbers: true,
symbols: true,
});
};
const changePassword = (values) => {
const data = {
username: props.username,
password: values.password,
};
axios(configApiCall(api_path_put_update_user, "PUT", data, null))
.then(() => {
props.setChangePasswordOpen(false);
})
.catch((error) => {
console.log(
"Updating user " +
props.username +
" password failed with error: " +
error
);
});
props.setChangePasswordOpen(false);
};
const passwordSchema = Yup.object().shape({
password: Yup.string().required("Password is required"),
passwordConfirmation: Yup.string().oneOf(
[Yup.ref("password"), null],
"Passwords must match"
),
});
const handleMouseDownPassword = () => {
setPasswordVisible(true);
};
const handleMouseUpPassword = () => {
setPasswordVisible(false);
};
const getStatus = () => {
if (copied)
return (
<span
style={{
fontSize: "12px",
marginRight: "10px",
marginTop: "14px",
color: "rgba(0, 0, 0, 0.54)",
}}
>
Copied
</span>
);
else if (generated) {
return (
<span
style={{
fontSize: "12px",
marginRight: "10px",
marginTop: "14px",
color: "rgba(0, 0, 0, 0.54)",
}}
>
Generated
</span>
);
} else return "";
};
React.useEffect(() => {
setCopied(false);
setGenerated(false);
}, []);
return (
<div>
<Dialog
open={props.changePasswordOpen}
onClose={props.handleClosechangePassword}
aria-labelledby="alert-dialog-title"
aria-describedby="alert-dialog-description"
>
<Formik
initialValues={{
password: "",
passwordConfirmation: "",
}}
validationSchema={passwordSchema}
onSubmit={changePassword}
>
{({ isValid, dirty, handleSubmit, values, setFieldValue }) => (
<form onSubmit={handleSubmit}>
<DialogContent>
<DialogContentText id="change-password-description">
Change <strong>{props.username}'s</strong> password{" "}
</DialogContentText>
<FormikField
name="password"
label="Password"
placeholder="Password"
type={passwordVisible ? "text" : "password"}
startAdornment={
<InputAdornment position="start">
<VpnKeyIcon />
</InputAdornment>
}
endAdornment={
<div style={{ display: "flex" }}>
{getStatus()}
<IconButton
aria-label="toggle password visibility"
onMouseDown={handleMouseDownPassword}
onMouseUp={handleMouseUpPassword}
>
{passwordVisible ? (
<VisibilityIcon />
) : (
<VisibilityOffIcon />
)}
</IconButton>
</div>
}
handleChange={() => {}}
onKeyUpError={false}
onKeyUpErrorMessage=""
/>
<FormikField
name="passwordConfirmation"
label="Confirm password"
placeholder="Confirm password"
type={passwordVisible ? "text" : "password"}
startAdornment={
<InputAdornment position="start">
<VpnKeyIcon />
</InputAdornment>
}
endAdornment={
<IconButton
aria-label="toggle password visibility"
onMouseDown={handleMouseDownPassword}
onMouseUp={handleMouseUpPassword}
>
{passwordVisible ? (
<VisibilityIcon />
) : (
<VisibilityOffIcon />
)}
</IconButton>
}
handleChange={() => {}}
onKeyUpError={false}
onKeyUpErrorMessage=""
/>
</DialogContent>
<DialogActions>
<Grid>
<Grid item>
<Button
variant="contained"
color="primary"
size="large"
className={classes.button}
startIcon={<RefreshIcon />}
onClick={() => {
const newGeneratedPassword = passwordGenerator();
setFieldValue("password", newGeneratedPassword, false);
setFieldValue(
"passwordConfirmation",
newGeneratedPassword,
false
);
setCopied(false);
setGenerated(true);
}}
>
{"Generate"}
</Button>
<CopyToClipboard
text={values.password}
onCopy={() => {
setCopied(true);
setGenerated(false);
}}
>
<Button
variant="contained"
color="primary"
size="large"
className={classes.button}
startIcon={<FileCopyIcon />}
>
Copy to clipboard
</Button>
</CopyToClipboard>
</Grid>
<Grid item className={classes.actionButtons}>
<Button
onClick={props.handleClosechangePassword}
color="primary"
>
Cancel
</Button>
<Button
type="submit"
disable={!isValid && !dirty}
color="info"
autoFocus
>
Update password
</Button>
</Grid>
</Grid>
</DialogActions>
</form>
)}
</Formik>
</Dialog>
</div>
);
}