diff --git a/client/package.json b/client/package.json
index 4ff4e45df..956f12bb9 100644
--- a/client/package.json
+++ b/client/package.json
@@ -4,9 +4,10 @@
"private": true,
"license": "UNLICENSED",
"dependencies": {
- "@apollo/react-hooks": "^3.1.3",
"antd": "^3.26.0",
"apollo-boost": "^0.4.4",
+ "apollo-link-context": "^1.0.19",
+ "apollo-link-logger": "^1.2.3",
"dotenv": "^8.2.0",
"firebase": "^7.5.0",
"graphql": "^14.5.8",
diff --git a/client/src/App/App.container.jsx b/client/src/App/App.container.jsx
index da9c2acad..c20d8f247 100644
--- a/client/src/App/App.container.jsx
+++ b/client/src/App/App.container.jsx
@@ -1,91 +1,29 @@
-//Baselined on https://blog.hasura.io/authentication-and-authorization-using-hasura-and-firebase/
+import React from "react";
+import { Mutation, Query } from "react-apollo";
+import { GET_CURRENT_USER, SET_CURRENT_USER } from "../graphql/local.queries";
-import React, { useState, useEffect } from "react";
-import firebase from "../firebase/firebase.utils";
import App from "./App";
-
-import { gql } from "apollo-boost";
-import { HttpLink } from "apollo-link-http";
-import ApolloClient from "apollo-client";
-import { InMemoryCache } from "apollo-cache-inmemory";
-
import Spin from "../components/loading-spinner/loading-spinner.component";
-const UPSERT_USER = gql`
- mutation upsert_user($authEmail: String!, $authToken: String!) {
- insert_users(
- objects: [{ email: $authEmail, authid: $authToken }]
- on_conflict: { constraint: users_pkey, update_columns: [authid] }
- ) {
- returning {
- authid
- }
- }
- }
-`;
-
-const SET_CURRENT_USER = gql`
- mutation SetCurrentUser($user: User!) {
- setCurrentUser(user: $user) @client
- }
-`;
-
-const client = new ApolloClient({
- link: new HttpLink({
- uri: process.env.REACT_APP_GRAPHQL_ENDPOINT
- }),
- cache: new InMemoryCache()
-});
-
-export default function Auth() {
- const [authState, setAuthState] = useState({ status: "loading" });
-
- useEffect(() => {
- return firebase.auth().onAuthStateChanged(async user => {
- if (user) {
- console.log("Current User:", user);
-
- client
- .mutate({
- mutation: UPSERT_USER,
- variables: { authEmail: user.email, authToken: user.uid }
- })
- .then(r => console.log("Successful Upsert", r))
- .catch(error => console.log("Upsert error!!!!", error));
-
- const token = await user.getIdToken();
- const idTokenResult = await user.getIdTokenResult();
- const hasuraClaim =
- idTokenResult.claims["https://hasura.io/jwt/claims"];
- if (hasuraClaim) {
- setAuthState({ status: "in", user, token });
- } else {
- // Check if refresh is required.
- const metadataRef = firebase
- .database()
- .ref("metadata/" + user.uid + "/refreshTime");
- metadataRef.on("value", async () => {
- // Force refresh to pick up the latest custom claims changes.
- const token = await user.getIdToken(true);
- setAuthState({ status: "in", user, token });
- });
- }
- } else {
- setAuthState({ status: "out" });
- }
- });
- }, []);
-
- let content;
- if (authState.status === "loading") {
- content = ;
- } else {
- content = (
- <>
-
- >
- );
- }
-
- return
{content}
;
-}
+export default () => {
+ return (
+
+ {({ loading, error, data: { currentUser } }) => {
+ if (loading) return ;
+ if (error) return error.message;
+ return (
+
+ {setCurrentUser => (
+ {
+ setCurrentUser({ variables: { user } });
+ }}
+ />
+ )}
+
+ );
+ }}
+
+ );
+};
diff --git a/client/src/App/App.container.jsx.bak b/client/src/App/App.container.jsx.bak
new file mode 100644
index 000000000..50aa92e44
--- /dev/null
+++ b/client/src/App/App.container.jsx.bak
@@ -0,0 +1,78 @@
+//Baselined on https://blog.hasura.io/authentication-and-authorization-using-hasura-and-firebase/
+
+import React, { useState, useEffect } from "react";
+import firebase from "../firebase/firebase.utils";
+import App from "./App";
+
+import { gql } from "apollo-boost";
+import { HttpLink } from "apollo-link-http";
+import ApolloClient from "apollo-client";
+import { InMemoryCache } from "apollo-cache-inmemory";
+
+import Spin from "../components/loading-spinner/loading-spinner.component";
+
+const UPSERT_USER = gql`
+ mutation upsert_user($authEmail: String!, $authToken: String!) {
+ insert_users(
+ objects: [{ email: $authEmail, authid: $authToken }]
+ on_conflict: { constraint: users_pkey, update_columns: [authid] }
+ ) {
+ returning {
+ authid
+ }
+ }
+ }
+`;
+
+export default function Auth() {
+ const [authState, setAuthState] = useState({ status: "loading" });
+
+ useEffect(() => {
+ return firebase.auth().onAuthStateChanged(async user => {
+ if (user) {
+ console.log("Current User:", user);
+
+ client
+ .mutate({
+ mutation: UPSERT_USER,
+ variables: { authEmail: user.email, authToken: user.uid }
+ })
+ .then(r => console.log("Successful Upsert", r))
+ .catch(error => console.log("Upsert error!!!!", error));
+
+ const token = await user.getIdToken();
+ const idTokenResult = await user.getIdTokenResult();
+ const hasuraClaim =
+ idTokenResult.claims["https://hasura.io/jwt/claims"];
+ if (hasuraClaim) {
+ setAuthState({ status: "in", user, token });
+ } else {
+ // Check if refresh is required.
+ const metadataRef = firebase
+ .database()
+ .ref("metadata/" + user.uid + "/refreshTime");
+ metadataRef.on("value", async () => {
+ // Force refresh to pick up the latest custom claims changes.
+ const token = await user.getIdToken(true);
+ setAuthState({ status: "in", user, token });
+ });
+ }
+ } else {
+ setAuthState({ status: "out" });
+ }
+ });
+ }, []);
+
+ let content;
+ if (authState.status === "loading") {
+ content = ;
+ } else {
+ content = (
+ <>
+
+ >
+ );
+ }
+
+ return {content}
;
+}
diff --git a/client/src/App/App.js b/client/src/App/App.js
index 0d808c328..565448016 100644
--- a/client/src/App/App.js
+++ b/client/src/App/App.js
@@ -1,71 +1,105 @@
import React from "react";
-import { Switch, Route, Redirect } from "react-router";
-import { ApolloProvider } from "react-apollo";
-import { HttpLink } from "apollo-link-http";
-import ApolloClient from "apollo-client";
-import { InMemoryCache } from "apollo-cache-inmemory";
-import { resolvers, typeDefs } from "../graphql/resolvers";
-import initialState from "../graphql/initial-state";
-import { gql } from "apollo-boost";
-//Styling imports
+import { Switch, Route } from "react-router-dom";
+import firebase from "../firebase/firebase.utils";
+
import "./App.css";
//Component Imports
import LandingPage from "../pages/landing/landing.page";
import Manage from "../pages/manage/manage.page";
-
import PrivateRoute from "../utils/private-route";
-import SignInContainer from "../pages/sign-in/sign-in.container";
+import SignInPage from "../pages/sign-in/sign-in.page";
import Unauthorized from "../pages/unauthorized/unauthorized.component";
-const graphqlEndpoint = process.env.REACT_APP_GRAPHQL_ENDPOINT;
+import { auth } from "../firebase/firebase.utils";
-export default function App({ authState }) {
- const isIn = authState.status === "in";
- const headers = isIn ? { Authorization: `Bearer ${authState.token}` } : {};
- const httpLink = new HttpLink({
- uri: graphqlEndpoint,
- headers
- });
- const client = new ApolloClient({
- link: httpLink,
- cache: new InMemoryCache(),
- resolvers,
- typeDefs
- });
+class App extends React.Component {
+ unsubscribeFromAuth = null;
- //Init local state.
- client.writeData({
- data: {
- ...initialState,
- currentUser: {
- __typename: null,
- email: authState.user ? authState.user.email : null,
- displayName: authState.user ? authState.user.displayName : null
+ componentDidMount() {
+ const { setCurrentUser } = this.props;
+
+ this.unsubscribeFromAuth = auth.onAuthStateChanged(async user => {
+ console.log("Current User:", user);
+ if (user) {
+ // client
+ // .mutate({
+ // mutation: UPSERT_USER,
+ // variables: { authEmail: user.email, authToken: user.uid }
+ // })
+ // .then(r => console.log("Successful Upsert", r))
+ // .catch(error => console.log("Upsert error!!!!", error));
+
+ const token = await user.getIdToken();
+ const idTokenResult = await user.getIdTokenResult();
+ const hasuraClaim =
+ idTokenResult.claims["https://hasura.io/jwt/claims"];
+ if (hasuraClaim) {
+ setCurrentUser({
+ email: user.email,
+ displayName: user.displayName,
+ token
+ });
+ } else {
+ // Check if refresh is required.
+ const metadataRef = firebase
+ .database()
+ .ref("metadata/" + user.uid + "/refreshTime");
+ metadataRef.on("value", async () => {
+ // Force refresh to pick up the latest custom claims changes.
+ const token = await user.getIdToken(true);
+ setCurrentUser({
+ email: user.email,
+ displayName: user.displayName,
+ token
+ });
+ });
+ }
+
+ //add the bearer token to the headers.
+ localStorage.setItem("token", token);
+ } else {
+ setCurrentUser({
+ email: null,
+ displayName: null,
+ token: null
+ });
+ localStorage.removeItem("token");
}
- }
- });
+ });
+ }
- return (
-
- {authState.status}
-
-
-
-
- authState.status == "in" ? (
-
- ) : (
-
- )
- }
- />
- {/* */}
-
-
-
- );
+ componentWillUnmount() {
+ this.unsubscribeFromAuth();
+ }
+
+ render() {
+ return (
+
+
+
+
+ {/*
+ this.props.currentUser.email != null ? (
+
+ ) : (
+
+ )
+ }
+ /> */}
+
+
+
+
+ );
+ }
}
+
+export default App;
diff --git a/client/src/App/App.js.bak b/client/src/App/App.js.bak
new file mode 100644
index 000000000..0d808c328
--- /dev/null
+++ b/client/src/App/App.js.bak
@@ -0,0 +1,71 @@
+import React from "react";
+import { Switch, Route, Redirect } from "react-router";
+import { ApolloProvider } from "react-apollo";
+import { HttpLink } from "apollo-link-http";
+import ApolloClient from "apollo-client";
+import { InMemoryCache } from "apollo-cache-inmemory";
+import { resolvers, typeDefs } from "../graphql/resolvers";
+import initialState from "../graphql/initial-state";
+import { gql } from "apollo-boost";
+//Styling imports
+import "./App.css";
+
+//Component Imports
+import LandingPage from "../pages/landing/landing.page";
+import Manage from "../pages/manage/manage.page";
+
+import PrivateRoute from "../utils/private-route";
+import SignInContainer from "../pages/sign-in/sign-in.container";
+import Unauthorized from "../pages/unauthorized/unauthorized.component";
+
+const graphqlEndpoint = process.env.REACT_APP_GRAPHQL_ENDPOINT;
+
+export default function App({ authState }) {
+ const isIn = authState.status === "in";
+ const headers = isIn ? { Authorization: `Bearer ${authState.token}` } : {};
+ const httpLink = new HttpLink({
+ uri: graphqlEndpoint,
+ headers
+ });
+ const client = new ApolloClient({
+ link: httpLink,
+ cache: new InMemoryCache(),
+ resolvers,
+ typeDefs
+ });
+
+ //Init local state.
+ client.writeData({
+ data: {
+ ...initialState,
+ currentUser: {
+ __typename: null,
+ email: authState.user ? authState.user.email : null,
+ displayName: authState.user ? authState.user.displayName : null
+ }
+ }
+ });
+
+ return (
+
+ {authState.status}
+
+
+
+
+ authState.status == "in" ? (
+
+ ) : (
+
+ )
+ }
+ />
+ {/* */}
+
+
+
+ );
+}
diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx
index 981f3411a..47f96917a 100644
--- a/client/src/components/header/header.component.jsx
+++ b/client/src/components/header/header.component.jsx
@@ -1,4 +1,4 @@
-import React, { Component, useState } from "react";
+import React from "react";
import { Link } from "react-router-dom";
import { Menu, Icon } from "antd";
import "./header.styles.scss";
@@ -7,9 +7,9 @@ import SignOut from "../sign-out/sign-out.component";
export default ({ selectedNavItem, navItems }) => {
const handleClick = e => {
console.log("click ", e);
- this.setState({
- current: e.key
- });
+ // this.setState({
+ // current: e.key
+ // });
};
return (
diff --git a/client/src/components/sign-in-form/sign-in-form.component.jsx b/client/src/components/sign-in-form/sign-in-form.component.jsx
index 18bda3f60..393f3a875 100644
--- a/client/src/components/sign-in-form/sign-in-form.component.jsx
+++ b/client/src/components/sign-in-form/sign-in-form.component.jsx
@@ -65,11 +65,7 @@ class SignInForm extends React.Component {
Log in
- {errorMessage ? (
-
- ) : (
- null
- )}
+ {errorMessage ? : null}
);
}
diff --git a/client/src/components/sign-out/sign-out.component.jsx b/client/src/components/sign-out/sign-out.component.jsx
index 1f3d6c670..a9ab53f81 100644
--- a/client/src/components/sign-out/sign-out.component.jsx
+++ b/client/src/components/sign-out/sign-out.component.jsx
@@ -1,13 +1,11 @@
-import React, { useState } from "react";
+import React from "react";
import firebase from "../../firebase/firebase.utils";
export default function SignOut() {
- const [authState, setAuthState] = useState();
-
const signOut = async () => {
try {
- const p = await firebase.auth().signOut();
- setAuthState({ status: "out" });
+ await firebase.auth().signOut();
+ console.log("Signin out!");
} catch (error) {
console.log(error);
}
diff --git a/client/src/graphql/client.js b/client/src/graphql/client.js
new file mode 100644
index 000000000..926f92cc1
--- /dev/null
+++ b/client/src/graphql/client.js
@@ -0,0 +1,34 @@
+import ApolloClient from "apollo-client";
+import { InMemoryCache } from "apollo-cache-inmemory";
+import { HttpLink } from "apollo-link-http";
+import { setContext } from "apollo-link-context";
+import { resolvers, typeDefs } from "./resolvers";
+import apolloLogger from "apollo-link-logger";
+import { ApolloLink } from "apollo-boost";
+
+const httpLink = new HttpLink({
+ uri: process.env.REACT_APP_GRAPHQL_ENDPOINT
+});
+
+const authLink = setContext((_, { headers }) => {
+ // get the authentication token from local storage if it exists
+ const token = localStorage.getItem("token");
+ // return the headers to the context so httpLink can read them
+ if (token) {
+ return {
+ headers: {
+ ...headers,
+ authorization: token ? `Bearer ${token}` : ""
+ }
+ };
+ } else {
+ return { headers };
+ }
+});
+
+export const client = new ApolloClient({
+ link: authLink.concat(httpLink),
+ cache: new InMemoryCache({ addTypename: false }),
+ typeDefs,
+ resolvers
+});
diff --git a/client/src/graphql/initial-state.js b/client/src/graphql/initial-state.js
index 513254aeb..9e117e1ae 100644
--- a/client/src/graphql/initial-state.js
+++ b/client/src/graphql/initial-state.js
@@ -1,7 +1,8 @@
export default {
currentUser: {
email: null,
- displayName: null
+ displayName: null,
+ token: null
},
selectedNavItem: "Home",
recentItems: []
diff --git a/client/src/graphql/local.queries.js b/client/src/graphql/local.queries.js
new file mode 100644
index 000000000..84bb26e6b
--- /dev/null
+++ b/client/src/graphql/local.queries.js
@@ -0,0 +1,17 @@
+import { gql } from "apollo-boost";
+
+export const SET_CURRENT_USER = gql`
+ mutation SetCurrentUser($user: User!) {
+ setCurrentUser(user: $user) @client {
+ email
+ }
+ }
+`;
+
+export const GET_CURRENT_USER = gql`
+ {
+ currentUser @client {
+ email
+ }
+ }
+`;
diff --git a/client/src/graphql/metadata.queries.js b/client/src/graphql/metadata.queries.js
index 12cefb86c..788dbe049 100644
--- a/client/src/graphql/metadata.queries.js
+++ b/client/src/graphql/metadata.queries.js
@@ -21,14 +21,7 @@ export const GET_SELECTED_NAV_ITEM = gql`
}
`;
-export const GET_CURRENT_USER = gql`
- query GetCurrentUser {
- currentUser @client {
- email
- displayName
- }
- }
-`;
+
// export const SET_CURRENT_USER = gql`
// mutation SetCurrentUser($user User!){
diff --git a/client/src/graphql/resolvers.js b/client/src/graphql/resolvers.js
index d961016d1..c6553ec60 100644
--- a/client/src/graphql/resolvers.js
+++ b/client/src/graphql/resolvers.js
@@ -1,20 +1,15 @@
import { gql } from "apollo-boost";
+import { GET_CURRENT_USER } from "./local.queries";
export const typeDefs = gql`
extend type Mutation {
SetCurrentUser(user: User!): User!
}
- type User {
- displayName: String!,
- email: String!,
- photoUrl: String!
- }
-`;
-
-const GET_CURRENT_USER = gql`
- {
- currentUser @client
+ extend type User {
+ email: String!
+ displayName: String!
+ token: String!
}
`;
diff --git a/client/src/index.js b/client/src/index.js
index 459f19bc1..4de187462 100644
--- a/client/src/index.js
+++ b/client/src/index.js
@@ -5,14 +5,27 @@ import { BrowserRouter } from "react-router-dom";
import * as serviceWorker from "./serviceWorker";
import "./index.css";
-import { default as App } from "./App/App.container";
+import AppContainer from "./App/App.container";
+
+import { ApolloProvider } from "react-apollo";
+import { client } from "./graphql/client";
+import initialState from "./graphql/initial-state";
require("dotenv").config();
+//Init local state.
+client.writeData({
+ data: {
+ ...initialState
+ }
+});
+
ReactDOM.render(
-
-
- ,
+
+
+
+
+ ,
document.getElementById("root")
);
diff --git a/client/src/pages/sign-in/sign-in.container.jsx b/client/src/pages/sign-in/sign-in.container.jsx
deleted file mode 100644
index 77adbb00f..000000000
--- a/client/src/pages/sign-in/sign-in.container.jsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import React from "react";
-import { Query } from "react-apollo";
-
-import { Alert } from "antd";
-
-import Spin from "../../components/loading-spinner/loading-spinner.component";
-// import Skeleton from "../loading-skeleton/loading-skeleton.component";
-
-import { GET_CURRENT_USER } from "../../graphql/metadata.queries";
-import SignInPage from "./sign-in.page";
-
-const SignInContainer = () => {
- return (
-
- {({ loading, error, data: { currentUser } }) => {
- if (loading) return ;
- if (error) return ;
-
- return ;
- }}
-
- );
-};
-
-export default SignInContainer;
diff --git a/client/src/pages/sign-in/sign-in.page.jsx b/client/src/pages/sign-in/sign-in.page.jsx
index a58e0b408..a1f8c202c 100644
--- a/client/src/pages/sign-in/sign-in.page.jsx
+++ b/client/src/pages/sign-in/sign-in.page.jsx
@@ -1,14 +1,6 @@
import React from "react";
import SignInComponent from "../../components/sign-in-form/sign-in-form.component";
-import { Redirect } from "react-router-dom";
-
-
-export default ({signedIn}) => {
- console.log(signedIn)
- return (
-
-
-
- );
+export default () => {
+ return ;
};
diff --git a/client/yarn.lock b/client/yarn.lock
index 1f630b970..74bfd73cd 100644
--- a/client/yarn.lock
+++ b/client/yarn.lock
@@ -2189,6 +2189,14 @@ apollo-client@^2.6.4:
tslib "^1.9.3"
zen-observable "^0.8.0"
+apollo-link-context@^1.0.19:
+ version "1.0.19"
+ resolved "https://registry.yarnpkg.com/apollo-link-context/-/apollo-link-context-1.0.19.tgz#3c9ba5bf75ed5428567ce057b8837ef874a58987"
+ integrity sha512-TUi5TyufU84hEiGkpt+5gdH5HkB3Gx46npNfoxR4of3DKBCMuItGERt36RCaryGcU/C3u2zsICU3tJ+Z9LjFoQ==
+ dependencies:
+ apollo-link "^1.2.13"
+ tslib "^1.9.3"
+
apollo-link-error@^1.0.3:
version "1.1.12"
resolved "https://registry.yarnpkg.com/apollo-link-error/-/apollo-link-error-1.1.12.tgz#e24487bb3c30af0654047611cda87038afbacbf9"
@@ -2216,6 +2224,11 @@ apollo-link-http@^1.3.1:
apollo-link-http-common "^0.2.15"
tslib "^1.9.3"
+apollo-link-logger@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/apollo-link-logger/-/apollo-link-logger-1.2.3.tgz#1f3e6f7849ce7a7e3aa822141fe062cfa278b1e1"
+ integrity sha512-GaVwdHyXmawfvBlHfZkFkBHH3+YH7wibzSCc4/YpIbPVtbtZqi0Qop18w++jgpw385W083DMOdYe2eJsKkZdag==
+
apollo-link@^1.0.0, apollo-link@^1.0.6, apollo-link@^1.2.13:
version "1.2.13"
resolved "https://registry.yarnpkg.com/apollo-link/-/apollo-link-1.2.13.tgz#dff00fbf19dfcd90fddbc14b6a3f9a771acac6c4"