diff --git a/TicketManager.csproj b/TicketManager.csproj index 46c0c2f..d068f9e 100644 --- a/TicketManager.csproj +++ b/TicketManager.csproj @@ -14,9 +14,9 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -24,7 +24,6 @@ - diff --git a/client/src/App.tsx b/client/src/App.tsx index f388612..caa2e47 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -1,11 +1,10 @@ import React from "react"; import { Router } from "react-router-dom"; -import * as createHistory from "history"; import Layout from "./pages/Layout"; import { useAuth0 } from "./authentication/auth0"; - +// import history from "./utils/history"; +import * as createHistory from "history"; export const history = createHistory.createBrowserHistory(); - export default function App() { const { loading } = useAuth0(); @@ -14,10 +13,8 @@ export default function App() { } return ( - <> - - - - + + + ); } diff --git a/client/src/authentication/auth0.jsx b/client/src/authentication/auth0.jsx new file mode 100644 index 0000000..aa5194a --- /dev/null +++ b/client/src/authentication/auth0.jsx @@ -0,0 +1,90 @@ +// src/react-auth0-spa.js +import React, { useState, useEffect, useContext } from "react"; +import createAuth0Client from "@auth0/auth0-spa-js"; + +const DEFAULT_REDIRECT_CALLBACK = () => + window.history.replaceState({}, document.title, window.location.pathname); + +export const Auth0Context = React.createContext(); +export const useAuth0 = () => useContext(Auth0Context); +export const Auth0Provider = ({ + children, + onRedirectCallback = DEFAULT_REDIRECT_CALLBACK, + ...initOptions +}) => { + const [isAuthenticated, setIsAuthenticated] = useState(); + const [user, setUser] = useState(); + const [auth0Client, setAuth0] = useState(); + const [loading, setLoading] = useState(true); + const [popupOpen, setPopupOpen] = useState(false); + + useEffect(() => { + const initAuth0 = async () => { + const auth0FromHook = await createAuth0Client(initOptions); + setAuth0(auth0FromHook); + + if ( + window.location.search.includes("code=") && + window.location.search.includes("state=") + ) { + const { appState } = await auth0FromHook.handleRedirectCallback(); + onRedirectCallback(appState); + } + + const isAuthenticated = await auth0FromHook.isAuthenticated(); + + setIsAuthenticated(isAuthenticated); + + if (isAuthenticated) { + const user = await auth0FromHook.getUser(); + setUser(user); + } + + setLoading(false); + }; + initAuth0(); + // eslint-disable-next-line + }, []); + + const loginWithPopup = async (params = {}) => { + setPopupOpen(true); + try { + await auth0Client.loginWithPopup(params); + } catch (error) { + console.error(error); + } finally { + setPopupOpen(false); + } + const user = await auth0Client.getUser(); + setUser(user); + setIsAuthenticated(true); + }; + + const handleRedirectCallback = async () => { + setLoading(true); + await auth0Client.handleRedirectCallback(); + const user = await auth0Client.getUser(); + setLoading(false); + setIsAuthenticated(true); + setUser(user); + }; + return ( + auth0Client.getIdTokenClaims(...p), + loginWithRedirect: (...p) => auth0Client.loginWithRedirect(...p), + getTokenSilently: (...p) => auth0Client.getTokenSilently(...p), + getTokenWithPopup: (...p) => auth0Client.getTokenWithPopup(...p), + logout: (...p) => auth0Client.logout(...p) + }} + > + {children} + + ); +}; diff --git a/client/src/authentication/auth0.tsx b/client/src/authentication/auth0.tsx deleted file mode 100644 index 6be8707..0000000 --- a/client/src/authentication/auth0.tsx +++ /dev/null @@ -1,112 +0,0 @@ -import React, { useState, useEffect, useContext } from "react"; -import createAuth0Client from "@auth0/auth0-spa-js"; -import Auth0Client from "@auth0/auth0-spa-js/dist/typings/Auth0Client"; - -interface IAuth0Context { - isAuthenticated: boolean; - user: any; - loading: boolean; - popupOpen: boolean; - loginWithPopup(options: PopupLoginOptions): Promise; - handleRedirectCallback(): Promise; - getIdTokenClaims(o?: getIdTokenClaimsOptions): Promise; - loginWithRedirect(o: RedirectLoginOptions): Promise; - getTokenSilently(o?: GetTokenSilentlyOptions): Promise; - getTokenWithPopup(o?: GetTokenWithPopupOptions): Promise; - logout(o?: LogoutOptions): void; -} -export interface IAuth0ProviderOptions { - children: React.ReactElement; - onRedirectCallback?(result: RedirectLoginResult): void; -} - -const DEFAULT_REDIRECT_CALLBACK: () => void = () => - window.history.replaceState({}, document.title, window.location.pathname); - -export const Auth0Context: React.Context = React.createContext( - null -); -export const useAuth0: () => IAuth0Context = () => useContext(Auth0Context)!; -export const Auth0Provider = ({ - children, - onRedirectCallback = DEFAULT_REDIRECT_CALLBACK, - ...initOptions -}: IAuth0ProviderOptions & Auth0ClientOptions) => { - const [isAuthenticated, setIsAuthenticated] = useState(false); - const [user, setUser] = useState(); - const [auth0Client, setAuth0] = useState(); - const [loading, setLoading] = useState(true); - const [popupOpen, setPopupOpen] = useState(false); - - useEffect(() => { - const initAuth0 = async () => { - const auth0FromHook = await createAuth0Client(initOptions); - setAuth0(auth0FromHook); - - if (window.location.search.includes("code=")) { - const { appState } = await auth0FromHook.handleRedirectCallback(); - onRedirectCallback(appState); - } - - const isAuthenticated = await auth0FromHook.isAuthenticated(); - - setIsAuthenticated(isAuthenticated); - - if (isAuthenticated) { - const user = await auth0FromHook.getUser(); - setUser(user); - } - - setLoading(false); - }; - initAuth0(); - // eslint-disable-next-line - }, []); - - const loginWithPopup = async (o: PopupLoginOptions) => { - setPopupOpen(true); - try { - await auth0Client!.loginWithPopup(o); - } catch (error) { - console.error(error); - } finally { - setPopupOpen(false); - } - const user = await auth0Client!.getUser(); - setUser(user); - setIsAuthenticated(true); - }; - - const handleRedirectCallback = async () => { - setLoading(true); - const result = await auth0Client!.handleRedirectCallback(); - const user = await auth0Client!.getUser(); - setLoading(false); - setIsAuthenticated(true); - setUser(user); - return result; - }; - return ( - - auth0Client!.getIdTokenClaims(o), - loginWithRedirect: (o: RedirectLoginOptions) => - auth0Client!.loginWithRedirect(o), - getTokenSilently: (o: GetTokenSilentlyOptions | undefined) => - auth0Client!.getTokenSilently(o), - getTokenWithPopup: (o: GetTokenWithPopupOptions | undefined) => - auth0Client!.getTokenWithPopup(o), - logout: (o: LogoutOptions | undefined) => auth0Client!.logout(o) - }} - > - {children} - - ); -}; diff --git a/client/src/pages/TicketPage.tsx b/client/src/pages/TicketPage.tsx index b31fe93..7788dd2 100644 --- a/client/src/pages/TicketPage.tsx +++ b/client/src/pages/TicketPage.tsx @@ -17,10 +17,9 @@ import { makeStyles, Theme, Grid, - Typography, - Chip + Typography } from "@material-ui/core"; -import { Timer, InfoSharp } from "@material-ui/icons"; +import { Timer } from "@material-ui/icons"; interface IProps { viewModel: TicketVM; @@ -52,7 +51,6 @@ export const TicketPage: FC = ({ viewModel }) => { // let notes: string = ""; const classes = useStyles(); - const infos: InfoProps = { status, category, impact, difficulty }; return (
diff --git a/client/src/utils/PrivateRoute.jsx b/client/src/utils/PrivateRoute.jsx new file mode 100644 index 0000000..61f1d4d --- /dev/null +++ b/client/src/utils/PrivateRoute.jsx @@ -0,0 +1,24 @@ +import React, { useEffect } from "react"; +import { Route } from "react-router-dom"; +import { useAuth0 } from "../authentication/auth0"; + +export const PrivateRoute = ({ component: Component, path, ...rest }) => { + const { loading, isAuthenticated, loginWithRedirect } = useAuth0(); + + useEffect(() => { + if (loading || isAuthenticated) { + return; + } + const fn = async () => { + await loginWithRedirect({ + appState: { targetUrl: window.location.pathname } + }); + }; + fn(); + }, [loading, isAuthenticated, loginWithRedirect, path]); + + const render = props => + isAuthenticated === true ? : null; + + return ; +}; diff --git a/client/src/utils/router.tsx b/client/src/utils/router.tsx index d2d63c8..2d56d19 100644 --- a/client/src/utils/router.tsx +++ b/client/src/utils/router.tsx @@ -7,13 +7,14 @@ import { UserController } from "../controllers/UserController"; import { TicketController } from "../controllers/TicketController"; import { NotFoundPage } from "../pages/NotFoundPage"; import { TestPage } from "../pages/TestPage"; +import { PrivateRoute } from "./PrivateRoute"; export const AppRouter = () => { return ( - + {/* - + */}