Merge branch 'master' into feature/TW-310

This commit is contained in:
Sean Macfarlane
2020-05-13 12:17:15 -04:00
8 changed files with 45 additions and 27 deletions

View File

@@ -29,4 +29,5 @@ EXPOSE 3000
COPY --from=build /app /app
RUN npm run eslint
CMD ["npm", "start"]

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect } from 'react';
import React, { useState } from 'react';
import { Helmet } from 'react-helmet';
import { Switch, Redirect } from 'react-router-dom';
@@ -13,7 +13,7 @@ import ClientDevices from 'containers/ClientDevices';
import EditAccount from 'containers/EditAccount';
import UserProvider from 'contexts/UserProvider';
import { getItem } from 'utils/localStorage';
import { getItem, setItem } from 'utils/localStorage';
import { parseJwt } from 'utils/jwt';
import UnauthenticatedRoute from './components/UnauthenticatedRoute';
@@ -28,26 +28,32 @@ const RedirectToDashboard = () => (
);
const App = () => {
const [user, setUser] = useState({});
useEffect(() => {
const token = getItem(AUTH_TOKEN);
if (token) {
const { userId, userName, userRole, customerId } = parseJwt(token.access_token);
const token = getItem(AUTH_TOKEN);
let initialUser = {};
if (token) {
const { userId, userName, userRole, customerId } = parseJwt(token.access_token);
initialUser = { id: userId, email: userName, role: userRole, customerId };
}
const [user, setUser] = useState(initialUser);
const updateToken = newToken => {
setItem(AUTH_TOKEN, newToken);
if (newToken) {
const { userId, userName, userRole, customerId } = parseJwt(newToken.access_token);
setUser({ id: userId, email: userName, role: userRole, customerId });
}
}, []);
};
const updateUser = newUser => setUser({ ...user, ...newUser });
return (
<UserProvider
id={user.id}
email={user.email}
role={user.role}
id={user.userId}
email={user.userName}
role={user.userRole}
customerId={user.customerId}
updateUser={updateUser}
updateToken={updateToken}
>
<ThemeProvider company={COMPANY} logo={logo} logoMobile={logoMobile}>
<Helmet titleTemplate={`%s - ${COMPANY}`} defaultTitle={COMPANY}>

View File

@@ -1,12 +1,12 @@
import React from 'react';
import React, { useContext } from 'react';
import gql from 'graphql-tag';
import { useMutation, useApolloClient } from '@apollo/react-hooks';
import { useHistory } from 'react-router-dom';
import { notification } from 'antd';
import { Login as LoginPage } from '@tip-wlan/wlan-cloud-ui-library';
import { AUTH_TOKEN } from 'constants/index';
import { setItem } from 'utils/localStorage';
import UserContext from 'contexts/UserContext';
const AUTHENTICATE_USER = gql`
mutation AuthenticateUser($email: String!, $password: String!) {
@@ -20,6 +20,7 @@ const AUTHENTICATE_USER = gql`
const Login = () => {
const history = useHistory();
const { updateToken } = useContext(UserContext);
const client = useApolloClient();
const [authenticateUser] = useMutation(AUTHENTICATE_USER);
@@ -27,7 +28,7 @@ const Login = () => {
authenticateUser({ variables: { email, password } })
.then(({ data }) => {
client.resetStore();
setItem(AUTH_TOKEN, data.authenticateUser, data.authenticateUser.expires_in);
updateToken(data.authenticateUser);
history.push('/');
})
.catch(() =>

View File

@@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
import UserContext from 'contexts/UserContext';
const UserProvider = ({ children, id, email, role, customerId, updateUser }) => (
<UserContext.Provider value={{ id, email, role, customerId, updateUser }}>
const UserProvider = ({ children, id, email, role, customerId, updateUser, updateToken }) => (
<UserContext.Provider value={{ id, email, role, customerId, updateUser, updateToken }}>
{children}
</UserContext.Provider>
);
@@ -12,6 +12,7 @@ const UserProvider = ({ children, id, email, role, customerId, updateUser }) =>
UserProvider.propTypes = {
children: PropTypes.node.isRequired,
updateUser: PropTypes.func.isRequired,
updateToken: PropTypes.func.isRequired,
id: PropTypes.number,
email: PropTypes.string,
role: PropTypes.string,

View File

@@ -11,7 +11,7 @@ import 'styles/index.scss';
import App from 'containers/App';
import { AUTH_TOKEN } from 'constants/index';
import { getItem, setItem } from 'utils/localStorage';
import { getItem, setItem, removeItem } from 'utils/localStorage';
const API_URI = process.env.NODE_ENV !== 'production' ? 'http://localhost:4000/' : '';
const MOUNT_NODE = document.getElementById('root');
@@ -41,6 +41,7 @@ const client = new ApolloClient({
graphQLErrors.forEach(err => {
// handle errors differently based on its error code
switch (err.extensions.code) {
case 'FORBIDDEN':
case 'UNAUTHENTICATED':
operation.setContext({
headers: {
@@ -59,6 +60,11 @@ const client = new ApolloClient({
},
});
return forward(operation);
case 'INTERNAL_SERVER_ERROR':
if (err.path && err.path[0] === 'updateToken') {
removeItem(AUTH_TOKEN);
}
return forward(operation);
default:
return forward(operation);
}

View File

@@ -13,7 +13,9 @@ export const getItemExpiration = () => {
export const setItem = (key, data, expiration) => {
const localStorageState = data;
localStorageState.expiration = expiration || getItemExpiration();
if (localStorageState) {
localStorageState.expiration = expiration || getItemExpiration();
}
window.localStorage.setItem(key, JSON.stringify(localStorageState));
};

View File

@@ -1,8 +1,8 @@
version: '2.2'
services:
sut:
build:
context: .
dockerfile: Dockerfile.test
command: npm run test
services:
sut:
build:
context: .
dockerfile: Dockerfile.test
command: npm test

View File

@@ -12,7 +12,8 @@
"start": "cross-env NODE_ENV=development webpack-dev-server",
"build": "webpack --mode=production",
"format": "prettier --write \"app/**/*.js\"",
"eslint-fix": "eslint --fix \"app/**/*.js\""
"eslint-fix": "eslint --fix \"app/**/*.js\"",
"eslint": "eslint \"app/**/*.js\" --max-warnings=0"
},
"license": "MIT",
"dependencies": {