added history and auth0 provider

This commit is contained in:
Ruidy Nemausat 2020-03-05 15:39:19 +01:00
parent 73830344ed
commit 8036853803
5 changed files with 154 additions and 1 deletions

View file

@ -47,7 +47,7 @@
- [ ] error page redirect when offline.
- [x] ticket/files/activities list placeholders when empty
- [ ] think about public/private DTO's constructor, getters and setters
- [<span style="color:red">X</span>] write dtos without circular dependencies.
- [<span style="color:red">x</span>] write dtos without circular dependencies.
- [ ] use dtoRequest for PutProjects
- [ ] render avatarlist after UserModal Update
- [ ] Form validators

View file

@ -4,6 +4,19 @@
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"@auth0/auth0-spa-js": {
"version": "1.6.4",
"resolved": "https://registry.npmjs.org/@auth0/auth0-spa-js/-/auth0-spa-js-1.6.4.tgz",
"integrity": "sha512-zKUfUxOHL/YwSedP1BkKKRRrB4AJ7whMKBVlf6M7dTvVzeCrRzTWEXUF+HB4/iG4skVRyr+U35qQzMYoFWCxhw==",
"requires": {
"browser-tabs-lock": "^1.2.1",
"core-js": "^3.2.1",
"es-cookie": "^1.2.0",
"fast-text-encoding": "^1.0.0",
"promise-polyfill": "^8.1.3",
"unfetch": "^4.1.0"
}
},
"@babel/code-frame": {
"version": "7.8.3",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz",
@ -2702,6 +2715,11 @@
}
}
},
"browser-tabs-lock": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/browser-tabs-lock/-/browser-tabs-lock-1.2.7.tgz",
"integrity": "sha512-2H3EX1YstZEI8mkmoKPo7cIUfc0lJe2nysFQjcY4wRk/Z6Mb6jnDPYEloQNP0LQuBe4J7M1T78+sFE0gZagHDw=="
},
"browserify-aes": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
@ -4315,6 +4333,11 @@
"string.prototype.trimright": "^2.1.1"
}
},
"es-cookie": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/es-cookie/-/es-cookie-1.3.2.tgz",
"integrity": "sha512-UTlYYhXGLOy05P/vKVT2Ui7WtC7NiRzGtJyAKKn32g5Gvcjn7KAClLPWlipCtxIus934dFg9o9jXiBL0nP+t9Q=="
},
"es-to-primitive": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
@ -5171,6 +5194,11 @@
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc="
},
"fast-text-encoding": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fast-text-encoding/-/fast-text-encoding-1.0.0.tgz",
"integrity": "sha512-R9bHCvweUxxwkDwhjav5vxpFvdPGlVngtqmx4pIZfSUhM/Q4NiIUHB456BAf+Q1Nwu3HEZYONtu+Rya+af4jiQ=="
},
"faye-websocket": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.10.0.tgz",
@ -10219,6 +10247,11 @@
"resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
"integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM="
},
"promise-polyfill": {
"version": "8.1.3",
"resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-8.1.3.tgz",
"integrity": "sha512-MG5r82wBzh7pSKDRa9y+vllNHz3e3d4CNj1PQE4BQYxLme0gKYYBm9YENq+UkEikyZ0XbiGWxYlVw3Rl9O/U8g=="
},
"prompts": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.3.0.tgz",
@ -12549,6 +12582,11 @@
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.2.tgz",
"integrity": "sha512-D39qtimx0c1fI3ya1Lnhk3E9nONswSKhnffBI0gME9C99fYOkNi04xs8K6pePLhvl1frbDemkaBQ5ikWllR2HQ=="
},
"unfetch": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/unfetch/-/unfetch-4.1.0.tgz",
"integrity": "sha512-crP/n3eAPUJxZXM9T80/yv0YhkTEx2K1D3h7D1AJM6fzsWZrxdyRuLN0JH/dkZh1LNH8LxCnBzoPFCPbb2iGpg=="
},
"unicode-canonical-property-names-ecmascript": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz",

View file

@ -3,6 +3,7 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"@auth0/auth0-spa-js": "^1.6.4",
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.4.0",
"@testing-library/user-event": "^7.2.1",

View file

@ -0,0 +1,112 @@
import React, { useState, useEffect, useContext, FC } 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;
}
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>
);
};

View file

@ -0,0 +1,2 @@
import { createBrowserHistory } from "history";
export default createBrowserHistory;