build(deps): update dependency react-router-dom to v6 (#2565)
* build(deps): update dependency react-router-dom to v6 * fix(web): update code to conform to react-router 6 convention * refactor(web): react-router -> react-router-dom * refactor(web): make 2fa consts relative * refactor(web): rename 2fa consts for clarity Co-authored-by: Renovate Bot <bot@renovateapp.com> Co-authored-by: Amir Zarrinkafsh <nightah@me.com>pull/2529/head^2
parent
c8cddf4f16
commit
eae353e315
|
@ -19,8 +19,7 @@
|
||||||
"react-ga": "3.3.0",
|
"react-ga": "3.3.0",
|
||||||
"react-loading": "2.0.3",
|
"react-loading": "2.0.3",
|
||||||
"react-otp-input": "2.4.0",
|
"react-otp-input": "2.4.0",
|
||||||
"react-router": "5.2.1",
|
"react-router-dom": "6.0.0",
|
||||||
"react-router-dom": "5.3.0",
|
|
||||||
"u2f-api": "1.2.1"
|
"u2f-api": "1.2.1"
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -127,7 +126,6 @@
|
||||||
"@types/qrcode.react": "1.0.2",
|
"@types/qrcode.react": "1.0.2",
|
||||||
"@types/react": "17.0.34",
|
"@types/react": "17.0.34",
|
||||||
"@types/react-dom": "17.0.11",
|
"@types/react-dom": "17.0.11",
|
||||||
"@types/react-router-dom": "5.3.2",
|
|
||||||
"@typescript-eslint/eslint-plugin": "5.3.0",
|
"@typescript-eslint/eslint-plugin": "5.3.0",
|
||||||
"@typescript-eslint/parser": "5.3.0",
|
"@typescript-eslint/parser": "5.3.0",
|
||||||
"@vitejs/plugin-react": "1.0.7",
|
"@vitejs/plugin-react": "1.0.7",
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,7 +2,7 @@ import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { config as faConfig } from "@fortawesome/fontawesome-svg-core";
|
import { config as faConfig } from "@fortawesome/fontawesome-svg-core";
|
||||||
import { CssBaseline, ThemeProvider } from "@material-ui/core";
|
import { CssBaseline, ThemeProvider } from "@material-ui/core";
|
||||||
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom";
|
import { BrowserRouter as Router, Route, Routes } from "react-router-dom";
|
||||||
|
|
||||||
import NotificationBar from "@components/NotificationBar";
|
import NotificationBar from "@components/NotificationBar";
|
||||||
import {
|
import {
|
||||||
|
@ -64,32 +64,18 @@ const App: React.FC = () => {
|
||||||
<NotificationsContext.Provider value={{ notification, setNotification }}>
|
<NotificationsContext.Provider value={{ notification, setNotification }}>
|
||||||
<Router basename={getBasePath()}>
|
<Router basename={getBasePath()}>
|
||||||
<NotificationBar onClose={() => setNotification(null)} />
|
<NotificationBar onClose={() => setNotification(null)} />
|
||||||
<Switch>
|
<Routes>
|
||||||
<Route path={ResetPasswordStep1Route} exact>
|
<Route path={ResetPasswordStep1Route} element={<ResetPasswordStep1 />} />
|
||||||
<ResetPasswordStep1 />
|
<Route path={ResetPasswordStep2Route} element={<ResetPasswordStep2 />} />
|
||||||
</Route>
|
<Route path={RegisterSecurityKeyRoute} element={<RegisterSecurityKey />} />
|
||||||
<Route path={ResetPasswordStep2Route} exact>
|
<Route path={RegisterOneTimePasswordRoute} element={<RegisterOneTimePassword />} />
|
||||||
<ResetPasswordStep2 />
|
<Route path={LogoutRoute} element={<SignOut />} />
|
||||||
</Route>
|
<Route path={ConsentRoute} element={<ConsentView />} />
|
||||||
<Route path={RegisterSecurityKeyRoute} exact>
|
<Route
|
||||||
<RegisterSecurityKey />
|
path={`${FirstFactorRoute}*`}
|
||||||
</Route>
|
element={<LoginPortal rememberMe={getRememberMe()} resetPassword={getResetPassword()} />}
|
||||||
<Route path={RegisterOneTimePasswordRoute} exact>
|
/>
|
||||||
<RegisterOneTimePassword />
|
</Routes>
|
||||||
</Route>
|
|
||||||
<Route path={LogoutRoute} exact>
|
|
||||||
<SignOut />
|
|
||||||
</Route>
|
|
||||||
<Route path={ConsentRoute} exact>
|
|
||||||
<ConsentView />
|
|
||||||
</Route>
|
|
||||||
<Route path={FirstFactorRoute}>
|
|
||||||
<LoginPortal rememberMe={getRememberMe()} resetPassword={getResetPassword()} />
|
|
||||||
</Route>
|
|
||||||
<Route path="/">
|
|
||||||
<Redirect to={FirstFactorRoute} />
|
|
||||||
</Route>
|
|
||||||
</Switch>
|
|
||||||
</Router>
|
</Router>
|
||||||
</NotificationsContext.Provider>
|
</NotificationsContext.Provider>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|
|
@ -2,10 +2,10 @@ export const FirstFactorRoute: string = "/";
|
||||||
export const AuthenticatedRoute: string = "/authenticated";
|
export const AuthenticatedRoute: string = "/authenticated";
|
||||||
export const ConsentRoute: string = "/consent";
|
export const ConsentRoute: string = "/consent";
|
||||||
|
|
||||||
export const SecondFactorRoute: string = "/2fa";
|
export const SecondFactorRoute: string = "/2fa/";
|
||||||
export const SecondFactorU2FRoute: string = "/2fa/security-key";
|
export const SecondFactorU2FSubRoute: string = "security-key";
|
||||||
export const SecondFactorTOTPRoute: string = "/2fa/one-time-password";
|
export const SecondFactorTOTPSubRoute: string = "one-time-password";
|
||||||
export const SecondFactorPushRoute: string = "/2fa/push-notification";
|
export const SecondFactorPushSubRoute: string = "push-notification";
|
||||||
|
|
||||||
export const ResetPasswordStep1Route: string = "/reset-password/step1";
|
export const ResetPasswordStep1Route: string = "/reset-password/step1";
|
||||||
export const ResetPasswordStep2Route: string = "/reset-password/step2";
|
export const ResetPasswordStep2Route: string = "/reset-password/step2";
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import { useLocation } from "react-router";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
export function useRedirectionURL() {
|
export function useRedirectionURL() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import { useLocation } from "react-router";
|
import { useLocation } from "react-router-dom";
|
||||||
|
|
||||||
export function useRequestMethod() {
|
export function useRequestMethod() {
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
|
|
|
@ -6,7 +6,7 @@ import { makeStyles, Typography, Button, IconButton, Link, CircularProgress, Tex
|
||||||
import { red } from "@material-ui/core/colors";
|
import { red } from "@material-ui/core/colors";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import QRCode from "qrcode.react";
|
import QRCode from "qrcode.react";
|
||||||
import { useHistory, useLocation } from "react-router";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import AppStoreBadges from "@components/AppStoreBadges";
|
import AppStoreBadges from "@components/AppStoreBadges";
|
||||||
import { GoogleAuthenticator } from "@constants/constants";
|
import { GoogleAuthenticator } from "@constants/constants";
|
||||||
|
@ -18,7 +18,7 @@ import { extractIdentityToken } from "@utils/IdentityToken";
|
||||||
|
|
||||||
const RegisterOneTimePassword = function () {
|
const RegisterOneTimePassword = function () {
|
||||||
const style = useStyles();
|
const style = useStyles();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
// The secret retrieved from the API is all is ok.
|
// The secret retrieved from the API is all is ok.
|
||||||
const [secretURL, setSecretURL] = useState("empty");
|
const [secretURL, setSecretURL] = useState("empty");
|
||||||
|
@ -32,7 +32,7 @@ const RegisterOneTimePassword = function () {
|
||||||
const processToken = extractIdentityToken(location.search);
|
const processToken = extractIdentityToken(location.search);
|
||||||
|
|
||||||
const handleDoneClick = () => {
|
const handleDoneClick = () => {
|
||||||
history.push(FirstFactorRoute);
|
navigate(FirstFactorRoute);
|
||||||
};
|
};
|
||||||
|
|
||||||
const completeRegistrationProcess = useCallback(async () => {
|
const completeRegistrationProcess = useCallback(async () => {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState, useEffect, useCallback } from "react";
|
import React, { useState, useEffect, useCallback } from "react";
|
||||||
|
|
||||||
import { makeStyles, Typography, Button } from "@material-ui/core";
|
import { makeStyles, Typography, Button } from "@material-ui/core";
|
||||||
import { useHistory, useLocation } from "react-router";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
import u2fApi from "u2f-api";
|
import u2fApi from "u2f-api";
|
||||||
|
|
||||||
import FingerTouchIcon from "@components/FingerTouchIcon";
|
import FingerTouchIcon from "@components/FingerTouchIcon";
|
||||||
|
@ -13,7 +13,7 @@ import { extractIdentityToken } from "@utils/IdentityToken";
|
||||||
|
|
||||||
const RegisterSecurityKey = function () {
|
const RegisterSecurityKey = function () {
|
||||||
const style = useStyles();
|
const style = useStyles();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const { createErrorNotification } = useNotifications();
|
const { createErrorNotification } = useNotifications();
|
||||||
const [, setRegistrationInProgress] = useState(false);
|
const [, setRegistrationInProgress] = useState(false);
|
||||||
|
@ -21,7 +21,7 @@ const RegisterSecurityKey = function () {
|
||||||
const processToken = extractIdentityToken(location.search);
|
const processToken = extractIdentityToken(location.search);
|
||||||
|
|
||||||
const handleBackClick = () => {
|
const handleBackClick = () => {
|
||||||
history.push(FirstFactorPath);
|
navigate(FirstFactorPath);
|
||||||
};
|
};
|
||||||
|
|
||||||
const registerStep1 = useCallback(async () => {
|
const registerStep1 = useCallback(async () => {
|
||||||
|
@ -43,14 +43,14 @@ const RegisterSecurityKey = function () {
|
||||||
const registerResponse = await u2fApi.register(registerRequests, [], 60);
|
const registerResponse = await u2fApi.register(registerRequests, [], 60);
|
||||||
await completeU2FRegistrationProcessStep2(registerResponse);
|
await completeU2FRegistrationProcessStep2(registerResponse);
|
||||||
setRegistrationInProgress(false);
|
setRegistrationInProgress(false);
|
||||||
history.push(FirstFactorPath);
|
navigate(FirstFactorPath);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
createErrorNotification(
|
createErrorNotification(
|
||||||
"Failed to register your security key. The identity verification process might have timed out.",
|
"Failed to register your security key. The identity verification process might have timed out.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}, [processToken, createErrorNotification, history]);
|
}, [processToken, createErrorNotification, navigate]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
registerStep1();
|
registerStep1();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { Grid, makeStyles, Button } from "@material-ui/core";
|
import { Grid, makeStyles, Button } from "@material-ui/core";
|
||||||
import { useHistory } from "react-router";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import { LogoutRoute as SignOutRoute } from "@constants/Routes";
|
import { LogoutRoute as SignOutRoute } from "@constants/Routes";
|
||||||
import LoginLayout from "@layouts/LoginLayout";
|
import LoginLayout from "@layouts/LoginLayout";
|
||||||
|
@ -13,10 +13,10 @@ export interface Props {
|
||||||
|
|
||||||
const AuthenticatedView = function (props: Props) {
|
const AuthenticatedView = function (props: Props) {
|
||||||
const style = useStyles();
|
const style = useStyles();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const handleLogoutClick = () => {
|
const handleLogoutClick = () => {
|
||||||
history.push(SignOutRoute);
|
navigate(SignOutRoute);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,8 +2,9 @@ import React, { useEffect, Fragment, ReactNode } from "react";
|
||||||
|
|
||||||
import { Button, Grid, List, ListItem, ListItemIcon, ListItemText, Tooltip, makeStyles } from "@material-ui/core";
|
import { Button, Grid, List, ListItem, ListItemIcon, ListItemText, Tooltip, makeStyles } from "@material-ui/core";
|
||||||
import { AccountBox, CheckBox, Contacts, Drafts, Group } from "@material-ui/icons";
|
import { AccountBox, CheckBox, Contacts, Drafts, Group } from "@material-ui/icons";
|
||||||
import { useHistory } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
|
import { FirstFactorRoute } from "@constants/Routes";
|
||||||
import { useRequestedScopes } from "@hooks/Consent";
|
import { useRequestedScopes } from "@hooks/Consent";
|
||||||
import { useNotifications } from "@hooks/NotificationsContext";
|
import { useNotifications } from "@hooks/NotificationsContext";
|
||||||
import { useRedirector } from "@hooks/Redirector";
|
import { useRedirector } from "@hooks/Redirector";
|
||||||
|
@ -30,17 +31,17 @@ function showListItemAvatar(id: string) {
|
||||||
|
|
||||||
const ConsentView = function (props: Props) {
|
const ConsentView = function (props: Props) {
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const redirect = useRedirector();
|
const redirect = useRedirector();
|
||||||
const { createErrorNotification, resetNotification } = useNotifications();
|
const { createErrorNotification, resetNotification } = useNotifications();
|
||||||
const [resp, fetch, , err] = useRequestedScopes();
|
const [resp, fetch, , err] = useRequestedScopes();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (err) {
|
if (err) {
|
||||||
history.replace("/");
|
navigate(FirstFactorRoute);
|
||||||
console.error(`Unable to display consent screen: ${err.message}`);
|
console.error(`Unable to display consent screen: ${err.message}`);
|
||||||
}
|
}
|
||||||
}, [history, resetNotification, createErrorNotification, err]);
|
}, [navigate, resetNotification, createErrorNotification, err]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
fetch();
|
fetch();
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { MutableRefObject, useEffect, useRef, useState } from "react";
|
||||||
|
|
||||||
import { makeStyles, Grid, Button, FormControlLabel, Checkbox, Link } from "@material-ui/core";
|
import { makeStyles, Grid, Button, FormControlLabel, Checkbox, Link } from "@material-ui/core";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import { useHistory } from "react-router";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import FixedTextField from "@components/FixedTextField";
|
import FixedTextField from "@components/FixedTextField";
|
||||||
import { ResetPasswordStep1Route } from "@constants/Routes";
|
import { ResetPasswordStep1Route } from "@constants/Routes";
|
||||||
|
@ -24,7 +24,7 @@ export interface Props {
|
||||||
|
|
||||||
const FirstFactorForm = function (props: Props) {
|
const FirstFactorForm = function (props: Props) {
|
||||||
const style = useStyles();
|
const style = useStyles();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const redirectionURL = useRedirectionURL();
|
const redirectionURL = useRedirectionURL();
|
||||||
const requestMethod = useRequestMethod();
|
const requestMethod = useRequestMethod();
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ const FirstFactorForm = function (props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleResetPasswordClick = () => {
|
const handleResetPasswordClick = () => {
|
||||||
history.push(ResetPasswordStep1Route);
|
navigate(ResetPasswordStep1Route);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import React, { Fragment, ReactNode, useCallback, useEffect, useState } from "react";
|
import React, { Fragment, ReactNode, useCallback, useEffect, useState } from "react";
|
||||||
|
|
||||||
import { Redirect, Route, Switch, useHistory, useLocation } from "react-router";
|
import { Route, Routes, useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
AuthenticatedRoute,
|
AuthenticatedRoute,
|
||||||
FirstFactorRoute,
|
FirstFactorRoute,
|
||||||
SecondFactorPushRoute,
|
SecondFactorPushSubRoute,
|
||||||
SecondFactorRoute,
|
SecondFactorRoute,
|
||||||
SecondFactorTOTPRoute,
|
SecondFactorTOTPSubRoute,
|
||||||
SecondFactorU2FRoute,
|
SecondFactorU2FSubRoute,
|
||||||
} from "@constants/Routes";
|
} from "@constants/Routes";
|
||||||
import { useConfiguration } from "@hooks/Configuration";
|
import { useConfiguration } from "@hooks/Configuration";
|
||||||
import { useNotifications } from "@hooks/NotificationsContext";
|
import { useNotifications } from "@hooks/NotificationsContext";
|
||||||
|
@ -34,7 +34,7 @@ const RedirectionErrorMessage =
|
||||||
"Redirection was determined to be unsafe and aborted. Ensure the redirection URL is correct.";
|
"Redirection was determined to be unsafe and aborted. Ensure the redirection URL is correct.";
|
||||||
|
|
||||||
const LoginPortal = function (props: Props) {
|
const LoginPortal = function (props: Props) {
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
const location = useLocation();
|
||||||
const redirectionURL = useRedirectionURL();
|
const redirectionURL = useRedirectionURL();
|
||||||
const requestMethod = useRequestMethod();
|
const requestMethod = useRequestMethod();
|
||||||
|
@ -46,7 +46,7 @@ const LoginPortal = function (props: Props) {
|
||||||
const [userInfo, fetchUserInfo, , fetchUserInfoError] = userUserInfo();
|
const [userInfo, fetchUserInfo, , fetchUserInfoError] = userUserInfo();
|
||||||
const [configuration, fetchConfiguration, , fetchConfigurationError] = useConfiguration();
|
const [configuration, fetchConfiguration, , fetchConfigurationError] = useConfiguration();
|
||||||
|
|
||||||
const redirect = useCallback((url: string) => history.push(url), [history]);
|
const redirect = useCallback((url: string) => navigate(url), [navigate]);
|
||||||
|
|
||||||
// Fetch the state when portal is mounted.
|
// Fetch the state when portal is mounted.
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -128,11 +128,11 @@ const LoginPortal = function (props: Props) {
|
||||||
redirect(AuthenticatedRoute);
|
redirect(AuthenticatedRoute);
|
||||||
} else {
|
} else {
|
||||||
if (userInfo.method === SecondFactorMethod.U2F) {
|
if (userInfo.method === SecondFactorMethod.U2F) {
|
||||||
redirect(`${SecondFactorU2FRoute}${redirectionSuffix}`);
|
redirect(`${SecondFactorRoute}${SecondFactorU2FSubRoute}${redirectionSuffix}`);
|
||||||
} else if (userInfo.method === SecondFactorMethod.MobilePush) {
|
} else if (userInfo.method === SecondFactorMethod.MobilePush) {
|
||||||
redirect(`${SecondFactorPushRoute}${redirectionSuffix}`);
|
redirect(`${SecondFactorRoute}${SecondFactorPushSubRoute}${redirectionSuffix}`);
|
||||||
} else {
|
} else {
|
||||||
redirect(`${SecondFactorTOTPRoute}${redirectionSuffix}`);
|
redirect(`${SecondFactorRoute}${SecondFactorTOTPSubRoute}${redirectionSuffix}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -165,38 +165,41 @@ const LoginPortal = function (props: Props) {
|
||||||
location.pathname === FirstFactorRoute;
|
location.pathname === FirstFactorRoute;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Routes>
|
||||||
<Route path={FirstFactorRoute} exact>
|
<Route
|
||||||
<ComponentOrLoading ready={firstFactorReady}>
|
path={FirstFactorRoute}
|
||||||
<FirstFactorForm
|
element={
|
||||||
disabled={firstFactorDisabled}
|
<ComponentOrLoading ready={firstFactorReady}>
|
||||||
rememberMe={props.rememberMe}
|
<FirstFactorForm
|
||||||
resetPassword={props.resetPassword}
|
disabled={firstFactorDisabled}
|
||||||
onAuthenticationStart={() => setFirstFactorDisabled(true)}
|
rememberMe={props.rememberMe}
|
||||||
onAuthenticationFailure={() => setFirstFactorDisabled(false)}
|
resetPassword={props.resetPassword}
|
||||||
onAuthenticationSuccess={handleAuthSuccess}
|
onAuthenticationStart={() => setFirstFactorDisabled(true)}
|
||||||
/>
|
onAuthenticationFailure={() => setFirstFactorDisabled(false)}
|
||||||
</ComponentOrLoading>
|
onAuthenticationSuccess={handleAuthSuccess}
|
||||||
</Route>
|
/>
|
||||||
<Route path={SecondFactorRoute}>
|
</ComponentOrLoading>
|
||||||
{state && userInfo && configuration ? (
|
}
|
||||||
<SecondFactorForm
|
/>
|
||||||
authenticationLevel={state.authentication_level}
|
<Route
|
||||||
userInfo={userInfo}
|
path={`${SecondFactorRoute}*`}
|
||||||
configuration={configuration}
|
element={
|
||||||
onMethodChanged={() => fetchUserInfo()}
|
state && userInfo && configuration ? (
|
||||||
onAuthenticationSuccess={handleAuthSuccess}
|
<SecondFactorForm
|
||||||
/>
|
authenticationLevel={state.authentication_level}
|
||||||
) : null}
|
userInfo={userInfo}
|
||||||
</Route>
|
configuration={configuration}
|
||||||
<Route path={AuthenticatedRoute} exact>
|
onMethodChanged={() => fetchUserInfo()}
|
||||||
{userInfo ? <AuthenticatedView name={userInfo.display_name} /> : null}
|
onAuthenticationSuccess={handleAuthSuccess}
|
||||||
</Route>
|
/>
|
||||||
{/* By default we route to first factor page */}
|
) : null
|
||||||
<Route path="/">
|
}
|
||||||
<Redirect to={FirstFactorRoute} />
|
/>
|
||||||
</Route>
|
<Route
|
||||||
</Switch>
|
path={AuthenticatedRoute}
|
||||||
|
element={userInfo ? <AuthenticatedView name={userInfo.display_name} /> : null}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,14 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
|
|
||||||
import { Grid, makeStyles, Button } from "@material-ui/core";
|
import { Grid, makeStyles, Button } from "@material-ui/core";
|
||||||
import { useHistory, Switch, Route, Redirect } from "react-router";
|
import { Route, Routes, useNavigate } from "react-router-dom";
|
||||||
import u2fApi from "u2f-api";
|
import u2fApi from "u2f-api";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
LogoutRoute as SignOutRoute,
|
LogoutRoute as SignOutRoute,
|
||||||
SecondFactorTOTPRoute,
|
SecondFactorPushSubRoute,
|
||||||
SecondFactorPushRoute,
|
SecondFactorTOTPSubRoute,
|
||||||
SecondFactorU2FRoute,
|
SecondFactorU2FSubRoute,
|
||||||
SecondFactorRoute,
|
|
||||||
} from "@constants/Routes";
|
} from "@constants/Routes";
|
||||||
import { useNotifications } from "@hooks/NotificationsContext";
|
import { useNotifications } from "@hooks/NotificationsContext";
|
||||||
import LoginLayout from "@layouts/LoginLayout";
|
import LoginLayout from "@layouts/LoginLayout";
|
||||||
|
@ -38,7 +37,7 @@ export interface Props {
|
||||||
|
|
||||||
const SecondFactorForm = function (props: Props) {
|
const SecondFactorForm = function (props: Props) {
|
||||||
const style = useStyles();
|
const style = useStyles();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
const [methodSelectionOpen, setMethodSelectionOpen] = useState(false);
|
const [methodSelectionOpen, setMethodSelectionOpen] = useState(false);
|
||||||
const { createInfoNotification, createErrorNotification } = useNotifications();
|
const { createInfoNotification, createErrorNotification } = useNotifications();
|
||||||
const [registrationInProgress, setRegistrationInProgress] = useState(false);
|
const [registrationInProgress, setRegistrationInProgress] = useState(false);
|
||||||
|
@ -85,7 +84,7 @@ const SecondFactorForm = function (props: Props) {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogoutClick = () => {
|
const handleLogoutClick = () => {
|
||||||
history.push(SignOutRoute);
|
navigate(SignOutRoute);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -108,42 +107,48 @@ const SecondFactorForm = function (props: Props) {
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={12} className={style.methodContainer}>
|
<Grid item xs={12} className={style.methodContainer}>
|
||||||
<Switch>
|
<Routes>
|
||||||
<Route path={SecondFactorTOTPRoute} exact>
|
<Route
|
||||||
<OneTimePasswordMethod
|
path={SecondFactorTOTPSubRoute}
|
||||||
id="one-time-password-method"
|
element={
|
||||||
authenticationLevel={props.authenticationLevel}
|
<OneTimePasswordMethod
|
||||||
// Whether the user has a TOTP secret registered already
|
id="one-time-password-method"
|
||||||
registered={props.userInfo.has_totp}
|
authenticationLevel={props.authenticationLevel}
|
||||||
totp_period={props.configuration.totp_period}
|
// Whether the user has a TOTP secret registered already
|
||||||
onRegisterClick={initiateRegistration(initiateTOTPRegistrationProcess)}
|
registered={props.userInfo.has_totp}
|
||||||
onSignInError={(err) => createErrorNotification(err.message)}
|
totp_period={props.configuration.totp_period}
|
||||||
onSignInSuccess={props.onAuthenticationSuccess}
|
onRegisterClick={initiateRegistration(initiateTOTPRegistrationProcess)}
|
||||||
/>
|
onSignInError={(err) => createErrorNotification(err.message)}
|
||||||
</Route>
|
onSignInSuccess={props.onAuthenticationSuccess}
|
||||||
<Route path={SecondFactorU2FRoute} exact>
|
/>
|
||||||
<SecurityKeyMethod
|
}
|
||||||
id="security-key-method"
|
/>
|
||||||
authenticationLevel={props.authenticationLevel}
|
<Route
|
||||||
// Whether the user has a U2F device registered already
|
path={SecondFactorU2FSubRoute}
|
||||||
registered={props.userInfo.has_u2f}
|
element={
|
||||||
onRegisterClick={initiateRegistration(initiateU2FRegistrationProcess)}
|
<SecurityKeyMethod
|
||||||
onSignInError={(err) => createErrorNotification(err.message)}
|
id="security-key-method"
|
||||||
onSignInSuccess={props.onAuthenticationSuccess}
|
authenticationLevel={props.authenticationLevel}
|
||||||
/>
|
// Whether the user has a U2F device registered already
|
||||||
</Route>
|
registered={props.userInfo.has_u2f}
|
||||||
<Route path={SecondFactorPushRoute} exact>
|
onRegisterClick={initiateRegistration(initiateU2FRegistrationProcess)}
|
||||||
<PushNotificationMethod
|
onSignInError={(err) => createErrorNotification(err.message)}
|
||||||
id="push-notification-method"
|
onSignInSuccess={props.onAuthenticationSuccess}
|
||||||
authenticationLevel={props.authenticationLevel}
|
/>
|
||||||
onSignInError={(err) => createErrorNotification(err.message)}
|
}
|
||||||
onSignInSuccess={props.onAuthenticationSuccess}
|
/>
|
||||||
/>
|
<Route
|
||||||
</Route>
|
path={SecondFactorPushSubRoute}
|
||||||
<Route path={SecondFactorRoute}>
|
element={
|
||||||
<Redirect to={SecondFactorTOTPRoute} />
|
<PushNotificationMethod
|
||||||
</Route>
|
id="push-notification-method"
|
||||||
</Switch>
|
authenticationLevel={props.authenticationLevel}
|
||||||
|
onSignInError={(err) => createErrorNotification(err.message)}
|
||||||
|
onSignInSuccess={props.onAuthenticationSuccess}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Routes>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</LoginLayout>
|
</LoginLayout>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useEffect, useCallback, useState } from "react";
|
import React, { useEffect, useCallback, useState } from "react";
|
||||||
|
|
||||||
import { Typography, makeStyles } from "@material-ui/core";
|
import { Typography, makeStyles } from "@material-ui/core";
|
||||||
import { Redirect } from "react-router";
|
import { Navigate } from "react-router-dom";
|
||||||
|
|
||||||
import { FirstFactorRoute } from "@constants/Routes";
|
import { FirstFactorRoute } from "@constants/Routes";
|
||||||
import { useIsMountedRef } from "@hooks/Mounted";
|
import { useIsMountedRef } from "@hooks/Mounted";
|
||||||
|
@ -48,7 +48,7 @@ const SignOut = function (props: Props) {
|
||||||
if (redirectionURL && safeRedirect) {
|
if (redirectionURL && safeRedirect) {
|
||||||
redirector(redirectionURL);
|
redirector(redirectionURL);
|
||||||
} else {
|
} else {
|
||||||
return <Redirect to={FirstFactorRoute} />;
|
return <Navigate to={FirstFactorRoute} />;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React, { useState } from "react";
|
import React, { useState } from "react";
|
||||||
|
|
||||||
import { Grid, Button, makeStyles } from "@material-ui/core";
|
import { Grid, Button, makeStyles } from "@material-ui/core";
|
||||||
import { useHistory } from "react-router";
|
import { useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import FixedTextField from "@components/FixedTextField";
|
import FixedTextField from "@components/FixedTextField";
|
||||||
import { FirstFactorRoute } from "@constants/Routes";
|
import { FirstFactorRoute } from "@constants/Routes";
|
||||||
|
@ -14,7 +14,7 @@ const ResetPasswordStep1 = function () {
|
||||||
const [username, setUsername] = useState("");
|
const [username, setUsername] = useState("");
|
||||||
const [error, setError] = useState(false);
|
const [error, setError] = useState(false);
|
||||||
const { createInfoNotification, createErrorNotification } = useNotifications();
|
const { createInfoNotification, createErrorNotification } = useNotifications();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
|
|
||||||
const doInitiateResetPasswordProcess = async () => {
|
const doInitiateResetPasswordProcess = async () => {
|
||||||
if (username === "") {
|
if (username === "") {
|
||||||
|
@ -35,7 +35,7 @@ const ResetPasswordStep1 = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancelClick = () => {
|
const handleCancelClick = () => {
|
||||||
history.push(FirstFactorRoute);
|
navigate(FirstFactorRoute);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React, { useState, useCallback, useEffect } from "react";
|
||||||
|
|
||||||
import { Grid, Button, makeStyles } from "@material-ui/core";
|
import { Grid, Button, makeStyles } from "@material-ui/core";
|
||||||
import classnames from "classnames";
|
import classnames from "classnames";
|
||||||
import { useHistory, useLocation } from "react-router";
|
import { useLocation, useNavigate } from "react-router-dom";
|
||||||
|
|
||||||
import FixedTextField from "@components/FixedTextField";
|
import FixedTextField from "@components/FixedTextField";
|
||||||
import { FirstFactorRoute } from "@constants/Routes";
|
import { FirstFactorRoute } from "@constants/Routes";
|
||||||
|
@ -20,7 +20,7 @@ const ResetPasswordStep2 = function () {
|
||||||
const [errorPassword1, setErrorPassword1] = useState(false);
|
const [errorPassword1, setErrorPassword1] = useState(false);
|
||||||
const [errorPassword2, setErrorPassword2] = useState(false);
|
const [errorPassword2, setErrorPassword2] = useState(false);
|
||||||
const { createSuccessNotification, createErrorNotification } = useNotifications();
|
const { createSuccessNotification, createErrorNotification } = useNotifications();
|
||||||
const history = useHistory();
|
const navigate = useNavigate();
|
||||||
// Get the token from the query param to give it back to the API when requesting
|
// Get the token from the query param to give it back to the API when requesting
|
||||||
// the secret for OTP.
|
// the secret for OTP.
|
||||||
const processToken = extractIdentityToken(location.search);
|
const processToken = extractIdentityToken(location.search);
|
||||||
|
@ -69,7 +69,7 @@ const ResetPasswordStep2 = function () {
|
||||||
try {
|
try {
|
||||||
await resetPassword(password1);
|
await resetPassword(password1);
|
||||||
createSuccessNotification("Password has been reset.");
|
createSuccessNotification("Password has been reset.");
|
||||||
setTimeout(() => history.push(FirstFactorRoute), 1500);
|
setTimeout(() => navigate(FirstFactorRoute), 1500);
|
||||||
setFormDisabled(true);
|
setFormDisabled(true);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
@ -83,7 +83,7 @@ const ResetPasswordStep2 = function () {
|
||||||
|
|
||||||
const handleResetClick = () => doResetPassword();
|
const handleResetClick = () => doResetPassword();
|
||||||
|
|
||||||
const handleCancelClick = () => history.push(FirstFactorRoute);
|
const handleCancelClick = () => navigate(FirstFactorRoute);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<LoginLayout title="Enter new password" id="reset-password-step2-stage">
|
<LoginLayout title="Enter new password" id="reset-password-step2-stage">
|
||||||
|
|
Loading…
Reference in New Issue