mirror of
https://github.com/rjNemo/ticket_manager
synced 2026-06-12 11:46:40 +00:00
add Private ROute component
This commit is contained in:
parent
c5cb741b61
commit
058d70cb44
7 changed files with 127 additions and 130 deletions
|
|
@ -14,9 +14,9 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.2" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="3.0.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="3.0.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices" Version="3.0.2" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.1" />
|
<PackageReference Include="Microsoft.AspNetCore.SpaServices.Extensions" Version="3.0.2" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.1">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="3.0.1">
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
|
@ -24,7 +24,6 @@
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.0.1" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.1" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="3.0.1" />
|
||||||
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.1" />
|
|
||||||
<PackageReference Include="Microsoft.OpenApi" Version="1.1.4" />
|
<PackageReference Include="Microsoft.OpenApi" Version="1.1.4" />
|
||||||
<PackageReference Include="Moq" Version="4.13.1" />
|
<PackageReference Include="Moq" Version="4.13.1" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" />
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Router } from "react-router-dom";
|
import { Router } from "react-router-dom";
|
||||||
import * as createHistory from "history";
|
|
||||||
import Layout from "./pages/Layout";
|
import Layout from "./pages/Layout";
|
||||||
import { useAuth0 } from "./authentication/auth0";
|
import { useAuth0 } from "./authentication/auth0";
|
||||||
|
// import history from "./utils/history";
|
||||||
|
import * as createHistory from "history";
|
||||||
export const history = createHistory.createBrowserHistory();
|
export const history = createHistory.createBrowserHistory();
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { loading } = useAuth0();
|
const { loading } = useAuth0();
|
||||||
|
|
||||||
|
|
@ -14,10 +13,8 @@ export default function App() {
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<Router history={history}>
|
||||||
<Router history={history}>
|
<Layout />
|
||||||
<Layout />
|
</Router>
|
||||||
</Router>
|
|
||||||
</>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
90
client/src/authentication/auth0.jsx
Normal file
90
client/src/authentication/auth0.jsx
Normal file
|
|
@ -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 (
|
||||||
|
<Auth0Context.Provider
|
||||||
|
value={{
|
||||||
|
isAuthenticated,
|
||||||
|
user,
|
||||||
|
loading,
|
||||||
|
popupOpen,
|
||||||
|
loginWithPopup,
|
||||||
|
handleRedirectCallback,
|
||||||
|
getIdTokenClaims: (...p) => auth0Client.getIdTokenClaims(...p),
|
||||||
|
loginWithRedirect: (...p) => auth0Client.loginWithRedirect(...p),
|
||||||
|
getTokenSilently: (...p) => auth0Client.getTokenSilently(...p),
|
||||||
|
getTokenWithPopup: (...p) => auth0Client.getTokenWithPopup(...p),
|
||||||
|
logout: (...p) => auth0Client.logout(...p)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</Auth0Context.Provider>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -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<void>;
|
|
||||||
handleRedirectCallback(): Promise<RedirectLoginResult>;
|
|
||||||
getIdTokenClaims(o?: getIdTokenClaimsOptions): Promise<IdToken>;
|
|
||||||
loginWithRedirect(o: RedirectLoginOptions): Promise<void>;
|
|
||||||
getTokenSilently(o?: GetTokenSilentlyOptions): Promise<string | undefined>;
|
|
||||||
getTokenWithPopup(o?: GetTokenWithPopupOptions): Promise<string | undefined>;
|
|
||||||
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<IAuth0Context | null> = React.createContext<IAuth0Context | null>(
|
|
||||||
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<Auth0Client>();
|
|
||||||
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 (
|
|
||||||
<Auth0Context.Provider
|
|
||||||
value={{
|
|
||||||
isAuthenticated,
|
|
||||||
user,
|
|
||||||
loading,
|
|
||||||
popupOpen,
|
|
||||||
loginWithPopup,
|
|
||||||
handleRedirectCallback,
|
|
||||||
getIdTokenClaims: (o: getIdTokenClaimsOptions | undefined) =>
|
|
||||||
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}
|
|
||||||
</Auth0Context.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
@ -17,10 +17,9 @@ import {
|
||||||
makeStyles,
|
makeStyles,
|
||||||
Theme,
|
Theme,
|
||||||
Grid,
|
Grid,
|
||||||
Typography,
|
Typography
|
||||||
Chip
|
|
||||||
} from "@material-ui/core";
|
} from "@material-ui/core";
|
||||||
import { Timer, InfoSharp } from "@material-ui/icons";
|
import { Timer } from "@material-ui/icons";
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
viewModel: TicketVM;
|
viewModel: TicketVM;
|
||||||
|
|
@ -52,7 +51,6 @@ export const TicketPage: FC<IProps> = ({ viewModel }) => {
|
||||||
// let notes: string = "";
|
// let notes: string = "";
|
||||||
const classes = useStyles();
|
const classes = useStyles();
|
||||||
|
|
||||||
const infos: InfoProps = { status, category, impact, difficulty };
|
|
||||||
return (
|
return (
|
||||||
<Container maxWidth="md">
|
<Container maxWidth="md">
|
||||||
<div className={classes.root}>
|
<div className={classes.root}>
|
||||||
|
|
|
||||||
24
client/src/utils/PrivateRoute.jsx
Normal file
24
client/src/utils/PrivateRoute.jsx
Normal file
|
|
@ -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 ? <Component {...props} /> : null;
|
||||||
|
|
||||||
|
return <Route path={path} render={render} {...rest} />;
|
||||||
|
};
|
||||||
|
|
@ -7,13 +7,14 @@ import { UserController } from "../controllers/UserController";
|
||||||
import { TicketController } from "../controllers/TicketController";
|
import { TicketController } from "../controllers/TicketController";
|
||||||
import { NotFoundPage } from "../pages/NotFoundPage";
|
import { NotFoundPage } from "../pages/NotFoundPage";
|
||||||
import { TestPage } from "../pages/TestPage";
|
import { TestPage } from "../pages/TestPage";
|
||||||
|
import { PrivateRoute } from "./PrivateRoute";
|
||||||
|
|
||||||
export const AppRouter = () => {
|
export const AppRouter = () => {
|
||||||
return (
|
return (
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route exact path="/test">
|
{/* <PrivateRoute exact path="/test">
|
||||||
<TestPage />
|
<TestPage />
|
||||||
</Route>
|
</PrivateRoute> */}
|
||||||
|
|
||||||
<Route exact path="/">
|
<Route exact path="/">
|
||||||
<HomeController />
|
<HomeController />
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue