diff --git a/src/app/App.js b/src/app/App.js
index 2d5c4bc..aa08e73 100644
--- a/src/app/App.js
+++ b/src/app/App.js
@@ -5,11 +5,13 @@ import { CSSReset, ChakraProvider } from "@chakra-ui/core";
import defaultTheme from "@chakra-ui/theme";
import { BrowserRouter as Router, Switch, Route } from "react-router-dom";
import loadable from "@loadable/component";
+import { useAuth0 } from "@auth0/auth0-react";
-import apolloClient from "./apolloClient";
+import buildApolloClient from "./apolloClient";
-const WardrobePage = loadable(() => import("./WardrobePage"));
+const ItemsPage = loadable(() => import("./ItemsPage"));
const HomePage = loadable(() => import("./HomePage"));
+const WardrobePage = loadable(() => import("./WardrobePage"));
const theme = {
...defaultTheme,
@@ -39,22 +41,40 @@ function App() {
audience="https://impress-2020.openneo.net/api"
scope=""
>
-
+
+
+
+
-
+
);
}
+function ApolloProviderWithAuth0({ children }) {
+ const auth0 = useAuth0();
+ const auth0Ref = React.useRef(auth0);
+
+ React.useEffect(() => {
+ auth0Ref.current = auth0;
+ }, [auth0]);
+
+ const client = React.useMemo(
+ () => buildApolloClient(() => auth0Ref.current),
+ []
+ );
+ return {children};
+}
+
export default App;
diff --git a/src/app/HomePage.js b/src/app/HomePage.js
index 061b6ba..bcf7193 100644
--- a/src/app/HomePage.js
+++ b/src/app/HomePage.js
@@ -13,12 +13,13 @@ import {
useToast,
} from "@chakra-ui/core";
import { MoonIcon, SunIcon } from "@chakra-ui/icons";
-import { useHistory, useLocation } from "react-router-dom";
+import { Link, useHistory, useLocation } from "react-router-dom";
import { useLazyQuery } from "@apollo/client";
import { useAuth0 } from "@auth0/auth0-react";
import { Heading1, usePageTitle } from "./util";
import OutfitPreview from "./components/OutfitPreview";
+import useCurrentUser from "./components/useCurrentUser";
import HomepageSplashImg from "../images/homepage-splash.png";
import HomepageSplashImg2x from "../images/homepage-splash@2x.png";
@@ -76,32 +77,21 @@ function HomePage() {
}
function UserLoginLogout() {
- const {
- isLoading,
- user,
- isAuthenticated,
- loginWithRedirect,
- logout,
- } = useAuth0();
+ const { isLoading, isAuthenticated, loginWithRedirect, logout } = useAuth0();
+ const { id, username } = useCurrentUser();
if (isLoading) {
return null;
}
if (isAuthenticated) {
- // NOTE: Users created correctly should have these attributes... but I'm
- // coding defensively, because third-party integrations are always a
- // bit of a thing, and I don't want failures to crash us!
- const username = user["https://oauth.impress-2020.openneo.net/username"];
- const id = user.sub?.match(/^auth0\|impress-([0-9]+)$/)?.[1];
-
return (
{username && Hi, {username}!}
{id && (
+ );
+ }
+
+ if (error) {
+ return (
+
+ {error.message}
+
+ );
+ }
+
+ return (
+
+
+ {isCurrentUser ? "Items you own" : `Items ${data.user.username} owns`}
+
+
+ {data.user.itemsTheyOwn.map((item) => (
+
+
+ {item.name}
+
+ ))}
+
+
+ );
+}
+
+export default ItemsPage;
diff --git a/src/app/apolloClient.js b/src/app/apolloClient.js
index 207d564..0b06b19 100644
--- a/src/app/apolloClient.js
+++ b/src/app/apolloClient.js
@@ -1,4 +1,5 @@
import { ApolloClient, createHttpLink, InMemoryCache } from "@apollo/client";
+import { setContext } from "@apollo/client/link/context";
import { createPersistedQueryLink } from "apollo-link-persisted-queries";
import gql from "graphql-tag";
@@ -55,7 +56,7 @@ const typePolicies = {
// don't love escape-hatching to the client like this, but...
let cachedData;
try {
- cachedData = client.readQuery({
+ cachedData = hackyEscapeHatchClient.readQuery({
query: gql`
query CacheLookupForItemAppearanceReader(
$speciesId: ID!
@@ -105,6 +106,32 @@ const persistedQueryLink = createPersistedQueryLink({
useGETForHashedQueries: true,
});
const httpLink = createHttpLink({ uri: "/api/graphql" });
+const buildAuthLink = (getAuth0) =>
+ setContext(async (_, { headers }) => {
+ // Wait for auth0 to stop loading, so we can maybe get a token! We'll do
+ // this hackily by checking every 100ms until it's true.
+ await new Promise((resolve) => {
+ function check() {
+ if (getAuth0().isLoading) {
+ setTimeout(check, 100);
+ } else {
+ resolve();
+ }
+ }
+ check();
+ });
+
+ const { isAuthenticated, getAccessTokenSilently } = getAuth0();
+ if (isAuthenticated) {
+ const token = await getAccessTokenSilently();
+ return {
+ headers: {
+ ...headers,
+ authorization: token ? `Bearer ${token}` : "",
+ },
+ };
+ }
+ });
const initialCache = {};
for (const zone of cachedZones) {
@@ -115,10 +142,17 @@ for (const zone of cachedZones) {
* apolloClient is the global Apollo Client instance we use for GraphQL
* queries. This is how we communicate with the server!
*/
-const client = new ApolloClient({
- link: persistedQueryLink.concat(httpLink),
- cache: new InMemoryCache({ typePolicies }).restore(initialCache),
- connectToDevTools: true,
-});
+let hackyEscapeHatchClient = null;
+const buildClient = (getAuth0) => {
+ const client = new ApolloClient({
+ link: buildAuthLink(getAuth0).concat(persistedQueryLink).concat(httpLink),
+ cache: new InMemoryCache({ typePolicies }).restore(initialCache),
+ connectToDevTools: true,
+ });
-export default client;
+ hackyEscapeHatchClient = client;
+
+ return client;
+};
+
+export default buildClient;
diff --git a/src/app/components/useCurrentUser.js b/src/app/components/useCurrentUser.js
new file mode 100644
index 0000000..f1b6666
--- /dev/null
+++ b/src/app/components/useCurrentUser.js
@@ -0,0 +1,19 @@
+import { useAuth0 } from "@auth0/auth0-react";
+
+function useCurrentUser() {
+ const { isLoading, isAuthenticated, user } = useAuth0();
+
+ if (isLoading || !isAuthenticated) {
+ return { id: null, username: null };
+ }
+
+ // NOTE: Users created correctly should have these attributes... but I'm
+ // coding defensively, because third-party integrations are always a
+ // bit of a thing, and I don't want failures to crash us!
+ const id = user.sub?.match(/^auth0\|impress-([0-9]+)$/)?.[1];
+ const username = user["https://oauth.impress-2020.openneo.net/username"];
+
+ return { id, username };
+}
+
+export default useCurrentUser;