authelia/web/src/views/ResetPassword/ResetPasswordStep2.tsx
renovate[bot] 5f2edf3d42
build(deps): update dependency typescript to v4.4.2 (#2321)
* build(deps): update dependency typescript to v4.4.2

* fix(web): cast try catch err type to error

Typescript 4.x changes the default behaviour of try catch and its err type from `any` to [`unknown`](https://github.com/microsoft/TypeScript/pull/41013).

This change ensures that where we rely on said variable it is cast accordingly as an `Error`.

Co-authored-by: Renovate Bot <bot@renovateapp.com>
Co-authored-by: Amir Zarrinkafsh <nightah@me.com>
2021-09-04 23:27:11 +10:00

166 lines
6.0 KiB
TypeScript

import React, { useState, useCallback, useEffect } from "react";
import { Grid, Button, makeStyles } from "@material-ui/core";
import classnames from "classnames";
import { useHistory, useLocation } from "react-router";
import FixedTextField from "@components/FixedTextField";
import { FirstFactorRoute } from "@constants/Routes";
import { useNotifications } from "@hooks/NotificationsContext";
import LoginLayout from "@layouts/LoginLayout";
import { completeResetPasswordProcess, resetPassword } from "@services/ResetPassword";
import { extractIdentityToken } from "@utils/IdentityToken";
const ResetPasswordStep2 = function () {
const style = useStyles();
const location = useLocation();
const [formDisabled, setFormDisabled] = useState(true);
const [password1, setPassword1] = useState("");
const [password2, setPassword2] = useState("");
const [errorPassword1, setErrorPassword1] = useState(false);
const [errorPassword2, setErrorPassword2] = useState(false);
const { createSuccessNotification, createErrorNotification } = useNotifications();
const history = useHistory();
// Get the token from the query param to give it back to the API when requesting
// the secret for OTP.
const processToken = extractIdentityToken(location.search);
const completeProcess = useCallback(async () => {
if (!processToken) {
setFormDisabled(true);
createErrorNotification("No verification token provided");
return;
}
try {
setFormDisabled(true);
await completeResetPasswordProcess(processToken);
setFormDisabled(false);
} catch (err) {
console.error(err);
createErrorNotification(
"There was an issue completing the process. The verification token might have expired.",
);
setFormDisabled(true);
}
}, [processToken, createErrorNotification]);
useEffect(() => {
completeProcess();
}, [completeProcess]);
const doResetPassword = async () => {
if (password1 === "" || password2 === "") {
if (password1 === "") {
setErrorPassword1(true);
}
if (password2 === "") {
setErrorPassword2(true);
}
return;
}
if (password1 !== password2) {
setErrorPassword1(true);
setErrorPassword2(true);
createErrorNotification("Passwords do not match.");
return;
}
try {
await resetPassword(password1);
createSuccessNotification("Password has been reset.");
setTimeout(() => history.push(FirstFactorRoute), 1500);
setFormDisabled(true);
} catch (err) {
console.error(err);
if ((err as Error).message.includes("0000052D.")) {
createErrorNotification("Your supplied password does not meet the password policy requirements.");
} else {
createErrorNotification("There was an issue resetting the password.");
}
}
};
const handleResetClick = () => doResetPassword();
const handleCancelClick = () => history.push(FirstFactorRoute);
return (
<LoginLayout title="Enter new password" id="reset-password-step2-stage">
<Grid container className={style.root} spacing={2}>
<Grid item xs={12}>
<FixedTextField
id="password1-textfield"
label="New password"
variant="outlined"
type="password"
value={password1}
disabled={formDisabled}
onChange={(e) => setPassword1(e.target.value)}
error={errorPassword1}
className={classnames(style.fullWidth)}
autoComplete="new-password"
/>
</Grid>
<Grid item xs={12}>
<FixedTextField
id="password2-textfield"
label="Repeat new password"
variant="outlined"
type="password"
disabled={formDisabled}
value={password2}
onChange={(e) => setPassword2(e.target.value)}
error={errorPassword2}
onKeyPress={(ev) => {
if (ev.key === "Enter") {
doResetPassword();
ev.preventDefault();
}
}}
className={classnames(style.fullWidth)}
autoComplete="new-password"
/>
</Grid>
<Grid item xs={6}>
<Button
id="reset-button"
variant="contained"
color="primary"
name="password1"
disabled={formDisabled}
onClick={handleResetClick}
className={style.fullWidth}
>
Reset
</Button>
</Grid>
<Grid item xs={6}>
<Button
id="cancel-button"
variant="contained"
color="primary"
name="password2"
onClick={handleCancelClick}
className={style.fullWidth}
>
Cancel
</Button>
</Grid>
</Grid>
</LoginLayout>
);
};
export default ResetPasswordStep2;
const useStyles = makeStyles((theme) => ({
root: {
marginTop: theme.spacing(2),
marginBottom: theme.spacing(2),
},
fullWidth: {
width: "100%",
},
}));