master
Tudor Stanciu 2021-07-06 19:26:39 +03:00
parent 0586f20d52
commit fe812a371c
5 changed files with 78 additions and 44 deletions

View File

@ -1,4 +1,4 @@
import React, { Suspense } from "react"; import React, { useEffect } from "react";
import { HashRouter, Route, Switch, Redirect } from "react-router-dom"; import { HashRouter, Route, Switch, Redirect } from "react-router-dom";
// components // components
@ -10,31 +10,31 @@ import Login from "../pages/login";
// context // context
import { useUserState } from "../context/UserContext"; import { useUserState } from "../context/UserContext";
import { useTranslation } from "react-i18next";
export default function App() { export default function App() {
// global var { authenticated, messageCode } = useUserState();
var { isAuthenticated } = useUserState(); const { t } = useTranslation();
useEffect(() => {
if (!messageCode) return;
alert(t(messageCode));
}, [messageCode, t]);
return ( return (
<Suspense fallback={<div>Loading...</div>}> <HashRouter basename={process.env.PUBLIC_URL || ""}>
<HashRouter basename={process.env.PUBLIC_URL || ""}> <Switch>
<Switch> <Route exact path="/" render={() => <Redirect to="/app/dashboard" />} />
<Route <Route
exact exact
path="/" path="/app"
render={() => <Redirect to="/app/dashboard" />} render={() => <Redirect to="/app/dashboard" />}
/> />
<Route <PrivateRoute path="/app" component={Layout} />
exact <PublicRoute path="/login" component={Login} />
path="/app" <Route component={Error} />
render={() => <Redirect to="/app/dashboard" />} </Switch>
/> </HashRouter>
<PrivateRoute path="/app" component={Layout} />
<PublicRoute path="/login" component={Login} />
<Route component={Error} />
</Switch>
</HashRouter>
</Suspense>
); );
function PrivateRoute({ component, ...rest }) { function PrivateRoute({ component, ...rest }) {
@ -42,7 +42,7 @@ export default function App() {
<Route <Route
{...rest} {...rest}
render={(props) => render={(props) =>
isAuthenticated ? ( authenticated ? (
React.createElement(component, props) React.createElement(component, props)
) : ( ) : (
<Redirect <Redirect
@ -64,7 +64,7 @@ export default function App() {
<Route <Route
{...rest} {...rest}
render={(props) => render={(props) =>
isAuthenticated ? ( authenticated ? (
<Redirect <Redirect
to={{ to={{
pathname: "/" pathname: "/"

View File

@ -1,4 +1,5 @@
import React from "react"; import React from "react";
import { authenticate, invalidate, validateToken } from "../utils/identity";
var UserStateContext = React.createContext(); var UserStateContext = React.createContext();
var UserDispatchContext = React.createContext(); var UserDispatchContext = React.createContext();
@ -6,9 +7,15 @@ var UserDispatchContext = React.createContext();
function userReducer(state, action) { function userReducer(state, action) {
switch (action.type) { switch (action.type) {
case "LOGIN_SUCCESS": case "LOGIN_SUCCESS":
return { ...state, isAuthenticated: true }; return { ...state, authenticated: true };
case "SIGN_OUT_SUCCESS": case "SIGN_OUT_SUCCESS":
return { ...state, isAuthenticated: false }; return { ...state, authenticated: false };
case "LOGIN_FAILURE":
return {
...state,
authenticated: false,
messageCode: action.payload?.messageCode
};
default: { default: {
throw new Error(`Unhandled action type: ${action.type}`); throw new Error(`Unhandled action type: ${action.type}`);
} }
@ -17,7 +24,7 @@ function userReducer(state, action) {
function UserProvider({ children }) { function UserProvider({ children }) {
var [state, dispatch] = React.useReducer(userReducer, { var [state, dispatch] = React.useReducer(userReducer, {
isAuthenticated: !!localStorage.getItem("id_token"), authenticated: validateToken() === true
}); });
return ( return (
@ -45,32 +52,42 @@ function useUserDispatch() {
return context; return context;
} }
export { UserProvider, useUserState, useUserDispatch, loginUser, signOut }; function setLoginFailed(dispatch, setError, setIsLoading, messageCode) {
dispatch({ type: "LOGIN_FAILURE", payload: { messageCode } });
// ########################################################### setError(true);
setIsLoading(false);
}
function loginUser(dispatch, login, password, history, setIsLoading, setError) { function loginUser(dispatch, login, password, history, setIsLoading, setError) {
setError(false); setError(false);
setIsLoading(true); setIsLoading(true);
if (!!login && !!password) { if (!!login && !!password) {
setTimeout(() => { authenticate(login, password).then((response) => {
localStorage.setItem('id_token', 1) if (response.status === "SUCCESS") {
setError(null) setError(null);
setIsLoading(false) setIsLoading(false);
dispatch({ type: 'LOGIN_SUCCESS' }) dispatch({ type: "LOGIN_SUCCESS", payload: { token: response.token } });
} else if (response.status === "BAD_CREDENTIALS") {
setLoginFailed(
dispatch,
setError,
setIsLoading,
"Login.IncorrectCredentials"
);
}
});
history.push('/app/dashboard') history.push("/app/dashboard");
}, 2000);
} else { } else {
dispatch({ type: "LOGIN_FAILURE" }); setLoginFailed(dispatch, setError, setIsLoading, "Login.EmptyCredentials");
setError(true);
setIsLoading(false);
} }
} }
function signOut(dispatch, history) { function signOut(dispatch, history) {
localStorage.removeItem("id_token"); invalidate();
dispatch({ type: "SIGN_OUT_SUCCESS" }); dispatch({ type: "SIGN_OUT_SUCCESS" });
history.push("/login"); history.push("/login");
} }
export { UserProvider, useUserState, useUserDispatch, loginUser, signOut };

1
src/hooks/index.js Normal file
View File

@ -0,0 +1 @@
//export { useAuthorizationToken } from "./useAuthorizationToken";

View File

@ -1,4 +1,4 @@
import React from "react"; import React, { Suspense } from "react";
import ReactDOM from "react-dom"; import ReactDOM from "react-dom";
import { ThemeProvider } from "@material-ui/styles"; import { ThemeProvider } from "@material-ui/styles";
import { CssBaseline } from "@material-ui/core"; import { CssBaseline } from "@material-ui/core";
@ -14,7 +14,9 @@ ReactDOM.render(
<UserProvider> <UserProvider>
<ThemeProvider theme={Themes.default}> <ThemeProvider theme={Themes.default}>
<CssBaseline /> <CssBaseline />
<App /> <Suspense fallback={<div>Loading...</div>}>
<App />
</Suspense>
</ThemeProvider> </ThemeProvider>
</UserProvider> </UserProvider>
</LayoutProvider>, </LayoutProvider>,

View File

@ -32,4 +32,18 @@ const invalidate = () => {
} }
}; };
export { storageKeys, authenticate, invalidate }; const validateToken = () => {
const token = getItem(storageKeys.TOKEN);
if (!token) {
return false;
}
const valid = new Date(token.validUntil) >= new Date();
if (!valid) {
invalidate();
}
return valid;
};
export { storageKeys, authenticate, invalidate, validateToken };