Add request password reset route
This commit is contained in:
parent
fea2059433
commit
3e5648afca
@ -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>
|
||||||
)}
|
)}
|
||||||
|
@ -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 },
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
|
|
||||||
|
102
geneit_app/src/routes/auth/PasswordForgottenRoute.tsx
Normal file
102
geneit_app/src/routes/auth/PasswordForgottenRoute.tsx
Normal 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>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user