Add request password reset route

This commit is contained in:
Pierre HUBERT 2023-06-09 18:55:36 +02:00
parent fea2059433
commit 3e5648afca
4 changed files with 139 additions and 7 deletions

View File

@ -7,7 +7,11 @@ import { LoginRoute } from "./routes/auth/LoginRoute";
import { OIDCCbRoute } from "./routes/auth/OIDCCbRoute"; import { OIDCCbRoute } from "./routes/auth/OIDCCbRoute";
import { useAtom } from "jotai"; import { useAtom } from "jotai";
import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage"; import { BaseAuthenticatedPage } from "./widgets/BaseAuthenticatedPage";
import { PasswordForgottenRoute } from "./routes/auth/PasswordForgottenRoute";
/**
* Core app
*/
function App() { function App() {
const [signedIn] = useAtom(AuthApi.authStatus); const [signedIn] = useAtom(AuthApi.authStatus);
@ -19,6 +23,10 @@ function App() {
<Route path="*" element={<BaseLoginPage />}> <Route path="*" element={<BaseLoginPage />}>
<Route path="" element={<LoginRoute />} /> <Route path="" element={<LoginRoute />} />
<Route path="oidc_cb" element={<OIDCCbRoute />} /> <Route path="oidc_cb" element={<OIDCCbRoute />} />
<Route
path="password_forgotten"
element={<PasswordForgottenRoute />}
/>
<Route path="*" element={<NotFoundRoute />} /> <Route path="*" element={<NotFoundRoute />} />
</Route> </Route>
)} )}

View File

@ -62,4 +62,15 @@ export class AuthApi {
sessionStorage.removeItem(TokenStateKey); sessionStorage.removeItem(TokenStateKey);
} }
/**
* Request to reset password
*/
static async RequestResetPassword(mail: string): Promise<void> {
await APIClient.exec({
uri: "/auth/request_reset_password",
method: "POST",
jsonData: { mail: mail },
});
}
} }

View File

@ -2,12 +2,12 @@ import { Alert, CircularProgress } from "@mui/material";
import Box from "@mui/material/Box"; import Box from "@mui/material/Box";
import Button from "@mui/material/Button"; import Button from "@mui/material/Button";
import Grid from "@mui/material/Grid"; import Grid from "@mui/material/Grid";
import Link from "@mui/material/Link";
import TextField from "@mui/material/TextField"; import TextField from "@mui/material/TextField";
import Typography from "@mui/material/Typography"; import Typography from "@mui/material/Typography";
import * as React from "react"; import * as React from "react";
import { AuthApi } from "../../api/AuthApi"; import { AuthApi } from "../../api/AuthApi";
import { ServerApi } from "../../api/ServerApi"; import { ServerApi } from "../../api/ServerApi";
import { Link } from "react-router-dom";
/** /**
* Login form * Login form
@ -89,14 +89,25 @@ export function LoginRoute(): React.ReactElement {
<Grid container> <Grid container>
<Grid item xs> <Grid item xs>
<Link href="#" variant="body2"> <Typography variant="body2" color={"primary"}>
Mot de passe oublié <Link
</Link> to="/password_forgotten"
style={{ color: "inherit", textDecorationColor: "inherit" }}
>
Mot de passe oublié
</Link>
</Typography>
</Grid> </Grid>
<Grid item> <Grid item>
<Link href="#" variant="body2"> <Typography variant="body2" color={"primary"}>
Créer un nouveau compte {" "}
</Link> <Link
to="#"
style={{ color: "inherit", textDecorationColor: "inherit" }}
>
Créer un nouveau compte
</Link>
</Typography>
</Grid> </Grid>
</Grid> </Grid>

View File

@ -0,0 +1,102 @@
import {
Alert,
Box,
Button,
CircularProgress,
Grid,
TextField,
Typography,
} from "@mui/material";
import React from "react";
import { ServerApi } from "../../api/ServerApi";
import { Link } from "react-router-dom";
import { APIClient } from "../../api/ApiClient";
import { AuthApi } from "../../api/AuthApi";
export function PasswordForgottenRoute(): React.ReactElement {
const [loading, setLoading] = React.useState(false);
const [error, setError] = React.useState<string | null>(null);
const [success, setSuccess] = React.useState<string | null>(null);
const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault();
const data = new FormData(event.currentTarget);
try {
setError(null);
setSuccess(null);
setLoading(true);
await AuthApi.RequestResetPassword(data.get("email")!.toString());
setSuccess(
`Si l'adresse mail spécifiée est valide, alors la demande de réinitalisation de mot de passe a été traitée avec succès. Un courriel provenant de ${ServerApi.Config.mail} devrait alors être arrivé dans votre boîte mail.`
);
} catch (e) {
console.error(e);
setError("Echec de la demande de réinitialisation de mot de passe!");
}
setLoading(false);
};
if (loading)
return (
<>
<CircularProgress />
</>
);
return (
<>
{error && (
<Alert style={{ width: "100%" }} severity="error">
{error}
</Alert>
)}
{success && (
<Alert style={{ width: "100%" }} severity="success">
{success}
</Alert>
)}
<Typography component="h2" variant="body1">
Mot de passe oublié
</Typography>
<Box
component="form"
noValidate
onSubmit={handleSubmit}
sx={{ mt: 1 }}
style={{ width: "100%" }}
>
<TextField
margin="normal"
required
fullWidth
id="email"
label="Adresse mail"
name="email"
autoComplete="email"
autoFocus
/>
<Button
type="submit"
fullWidth
variant="contained"
sx={{ mt: 3, mb: 2 }}
>
Valider
</Button>
<Typography variant="body2" color={"primary"}>
<Link
to="/"
style={{ color: "inherit", textDecorationColor: "inherit" }}
>
Retour au formulaire de connexion
</Link>{" "}
</Typography>
</Box>
</>
);
}