Skip to content

Commit

Permalink
added X-CSRF token on every request
Browse files Browse the repository at this point in the history
  • Loading branch information
jalajcodes committed Aug 16, 2020
1 parent 3700d46 commit f109bf1
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 6 deletions.
63 changes: 59 additions & 4 deletions src/index.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,36 @@
import React, { useState } from 'react';
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import { ApolloClient, InMemoryCache, ApolloProvider } from '@apollo/client';
import { ApolloClient, InMemoryCache, ApolloProvider, useMutation, createHttpLink } from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { LOG_IN } from './lib/graphql/mutations/LogIn';
import { LogIn as LogInData, LogInVariables } from './lib/graphql/mutations/LogIn/__generated__/LogIn';
import * as serviceWorker from './serviceWorker';
import './styles/index.css';
import { Layout, Affix } from 'antd';
import { Layout, Affix, Spin } from 'antd';
import { Viewer } from './lib/types';

// Components
import { AppHeader, Home, User, Listings, Listing, Host, NotFound, Login } from './sections';
import { AppHeaderSkeleton, ErrorBanner } from './lib/components';

const client = new ApolloClient({
const authLink = setContext((_, { headers }) => {
// get the authentication token from session storage if it exists
const token = sessionStorage.getItem('token');
// return the headers to the context so httpLink can read them
return {
headers: {
'X-CSRF-TOKEN': token || '',
},
};
});

const httpLink = createHttpLink({
uri: '/api',
});

const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache(),
});

Expand All @@ -25,9 +44,45 @@ const initialViewer: Viewer = {

const App = () => {
const [viewer, setViewer] = useState<Viewer>(initialViewer);

const [login, { error }] = useMutation<LogInData, LogInVariables>(LOG_IN, {
onCompleted: (data) => {
if (data && data.login) {
setViewer(data.login);

if (data.login.token) {
sessionStorage.setItem('token', data.login.token);
} else {
sessionStorage.removeItem('token');
}
}
},
});

const loginRef = useRef(login);

useEffect(() => {
loginRef.current();
}, []);

const loginErrorBanner = error ? (
<ErrorBanner message="Something went wrong while you were being logged in. Please try again later! ;(" />
) : null;

if (!viewer.didRequest && !error) {
return (
<Layout className="app-skeleton">
<AppHeaderSkeleton />
<div className="app-skeleton__spin-section">
<Spin size="large" tip="Launching the App..." />
</div>
</Layout>
);
}
return (
<Router>
<Layout id="app">
{loginErrorBanner}
<Affix offsetTop={0} className="app__affix-header">
<AppHeader viewer={viewer} setViewer={setViewer} />
</Affix>
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 16 additions & 0 deletions src/lib/components/AppHeaderSkeleton/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { Layout } from 'antd';
import logo from './assets/hsh-logo-2.png';

const { Header } = Layout;
export const AppHeaderSkeleton = () => {
return (
<Header className="app-header">
<div className="app-header__logo-search-section">
<div className="app-header__logo">
<img src={logo} alt="HomeSweetHome Logo" />
</div>
</div>
</Header>
);
};
1 change: 1 addition & 0 deletions src/lib/components/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './ErrorBanner';
export * from './AppHeaderSkeleton';
1 change: 1 addition & 0 deletions src/sections/AppHeader/components/MenuItems/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export const MenuItems = ({ viewer, setViewer }: Props) => {
onCompleted: (data) => {
if (data && data.logout) {
setViewer(data.logout);
sessionStorage.removeItem('token');
displaySuccessNotification("You've Successfully Logged Out.");
}
},
Expand Down
11 changes: 9 additions & 2 deletions src/sections/Login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,29 @@ export const Login = ({ setViewer }: Props) => {
LogInVariables
>(LOG_IN, {
onCompleted: (data) => {
if (data && data.login) {
if (data && data.login && data.login.token) {
setViewer(data.login);
sessionStorage.setItem('token', data.login.token);
displaySuccessNotification("You've successfully logged in!");
}
},
});

// if query for auth url is successful, redirect.
if (authQueryData) {
window.location.href = authQueryData.authUrl;
}
if (authQueryError) {
displayErrorMessage("Sorry! We weren't able to log you in. Please try again later!");
}

// just to make useEffect believe logInMutation won't change during rerenders.
const logInRef = useRef(logInMutaion);

// after being redirected back from google consent form if
// the code param exists in the url, this useEffect hook will run
// the login mutation with the code variable, our backend uses this
// code to fetch details of the user.
useEffect(() => {
const code = new URL(window.location.href).searchParams.get('code');
if (code) {
Expand All @@ -49,7 +56,7 @@ export const Login = ({ setViewer }: Props) => {
}
}, []);

// Ant design
// Ant design components
const { Content } = Layout;
const { Title, Text } = Typography;

Expand Down

0 comments on commit f109bf1

Please sign in to comment.