Skip to content

Commit

Permalink
feat(auth): handle refresh token error
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristiaanScheermeijer committed Jul 30, 2021
1 parent 215abd2 commit 7a4a9eb
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 17 deletions.
21 changes: 20 additions & 1 deletion src/containers/AccountModal/AccountModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ import { useHistory } from 'react-router';
import { ConfigContext } from '../../providers/ConfigProvider';
import Dialog from '../../components/Dialog/Dialog';
import useQueryParam from '../../hooks/useQueryParam';
import { removeQueryParam } from '../../utils/history';
import { addQueryParam, removeQueryParam } from '../../utils/history';
import PaymentFailed from '../../components/PaymentFailed/PaymentFailed';
import Welcome from '../../components/Welcome/Welcome';
import { AccountStore } from '../../stores/AccountStore';
import LoadingOverlay from '../../components/LoadingOverlay/LoadingOverlay';

import styles from './AccountModal.module.scss';
import Login from './forms/Login';
Expand All @@ -15,17 +17,26 @@ import PersonalDetails from './forms/PersonalDetails';
import ChooseOffer from './forms/ChooseOffer';
import Checkout from './forms/Checkout';

const PUBLIC_VIEWS = ['login', 'create-account', 'forgot-password', 'reset-password'];

const AccountModal = () => {
const history = useHistory();
const viewParam = useQueryParam('u');
const [view, setView] = useState(viewParam);
const message = useQueryParam('message');
const { loading, auth } = AccountStore.useState((s) => s);

useEffect(() => {
// make sure the last view is rendered even when the modal gets closed
if (viewParam) setView(viewParam);
}, [viewParam]);

useEffect(() => {
if (!!viewParam && !loading && !auth && !PUBLIC_VIEWS.includes(viewParam)) {
history.push(addQueryParam(history, 'u', 'login'));
}
}, [viewParam, history, loading, auth]);

const {
assets: { banner },
} = useContext(ConfigContext);
Expand All @@ -35,6 +46,14 @@ const AccountModal = () => {
};

const renderForm = () => {
if (!auth && loading) {
return (
<div style={{ height: 300 }}>
<LoadingOverlay inline />
</div>
);
}

switch (view) {
case 'login':
return <Login />;
Expand Down
58 changes: 46 additions & 12 deletions src/stores/AccountStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,28 @@ import { ConfigStore } from './ConfigStore';
const PERSIST_KEY_ACCOUNT = 'auth';

type AccountStore = {
loading: boolean;
auth: AuthData | null;
user: Customer | null;
};

export const AccountStore = new Store<AccountStore>({
loading: true,
auth: null,
user: null,
});

const setLoading = (loading: boolean) => {
return AccountStore.update((s) => {
s.loading = loading;
});
}

export const initializeAccount = async () => {
const { config } = ConfigStore.getRawState();

if (!config.cleengId) setLoading(false);

const storedSession: AuthData | null = persist.getItem(PERSIST_KEY_ACCOUNT) as AuthData | null;
let refreshTimeout: number;

Expand All @@ -38,30 +49,41 @@ export const initializeAccount = async () => {
);

// restore session from localStorage
if (storedSession) {
const refreshedAuthData = await getFreshJwtToken(config.cleengSandbox, storedSession);
try {
if (storedSession) {
const refreshedAuthData = await getFreshJwtToken(config.cleengSandbox, storedSession);

if (refreshedAuthData) {
await afterLogin(config.cleengSandbox, refreshedAuthData);
if (refreshedAuthData) {
await afterLogin(config.cleengSandbox, refreshedAuthData);
}
}
} catch(error: unknown) {
await logout();
}

setLoading(false);
};

const getFreshJwtToken = async (sandbox: boolean, auth: AuthData) => {
const result = await accountService.refreshToken({ refreshToken: auth.refreshToken }, sandbox);

if (result?.responseData) {
return result.responseData;
}
if (result.errors.length) throw new Error(result.errors[0]);

return result?.responseData;
};

const refreshJwtToken = async (sandbox: boolean, auth: AuthData) => {
const authData = await getFreshJwtToken(sandbox, auth);
try {
const authData = await getFreshJwtToken(sandbox, auth);

if (authData) {
AccountStore.update((s) => {
s.auth = { ...s.auth, ...authData };
});
if (authData) {
AccountStore.update((s) => {
s.auth = { ...s.auth, ...authData };
});
}
} catch(error: unknown) {
// failed to refresh, logout user
await logout();
}
};

Expand All @@ -73,6 +95,7 @@ export const afterLogin = async (sandbox: boolean, auth: AuthData) => {
if (response.errors.length) throw new Error(response.errors[0]);

AccountStore.update((s) => {
s.loading = false;
s.auth = auth;
s.user = response.responseData;
});
Expand All @@ -85,13 +108,24 @@ export const login = async (email: string, password: string) => {

if (!cleengId) throw new Error('cleengId is not configured');

setLoading(true);

const response = await accountService.login({ email, password, publisherId: cleengId }, cleengSandbox);

if (response.errors.length > 0) throw new Error(response.errors[0]);

return afterLogin(cleengSandbox, response.responseData);
};

export const logout = async () => {
persist.removeItem(PERSIST_KEY_ACCOUNT);

AccountStore.update(s => {
s.auth = null;
s.user = null;
});
};

export const register = async (email: string, password: string) => {
const {
config: { cleengId, cleengSandbox },
Expand Down
16 changes: 12 additions & 4 deletions src/utils/persist.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,24 @@ const getItem = (key: string) => {
}
};

const removeItem = (key: string) => {
const storageKey = `${LOCAL_STORAGE_PREFIX}${key}`;

try {
window.localStorage.removeItem(storageKey);
} catch (error: unknown) {
console.error(error);
}
};

const parseJSON = (value?: string | null): unknown | undefined => {
if (!value) return;

try {
const parsedValue = JSON.parse(value);

return parsedValue;
return JSON.parse(value);
} catch (error: unknown) {
return;
}
};

export { setItem, getItem };
export { setItem, getItem, removeItem };

0 comments on commit 7a4a9eb

Please sign in to comment.