From a9c979481c9c23e067da2c19132a4352436d2935 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Chif=20Gerg=C5=91?= <chifgeri97@gmail.com>
Date: Mon, 28 Jun 2021 18:27:11 +0200
Subject: [PATCH] Handle logged in but no profile state

---
 src/client/auth.ts            |  9 ++++++---
 src/components/Header.tsx     |  4 ++--
 src/components/RememberMe.tsx |  6 ++++++
 src/context/UserContext.tsx   | 11 ++++++++---
 src/hooks/useMe.tsx           |  6 +++---
 5 files changed, 25 insertions(+), 11 deletions(-)

diff --git a/src/client/auth.ts b/src/client/auth.ts
index a7e8a69..017fb7f 100644
--- a/src/client/auth.ts
+++ b/src/client/auth.ts
@@ -1,7 +1,8 @@
 import Axios, { AxiosRequestConfig } from 'axios';
+import type { ProfileWithStatus } from '../context';
 import { IProfile } from '../types/Profile';
 
-type MeQuery = () => Promise<IProfile>;
+type MeQuery = () => Promise<ProfileWithStatus>;
 type RegisterQuery = (data: ProfileData) => Promise<any>;
 
 export type ProfileData = {
@@ -20,8 +21,10 @@ export function auth(config: AxiosRequestConfig): AuthClient {
     baseURL: `${config.baseURL}/api/v1/`,
   });
 
-  const me: MeQuery = async (): Promise<IProfile> => {
-    return (await axios.get<IProfile>('/users/me')).data;
+  const me: MeQuery = async (): Promise<ProfileWithStatus> => {
+    const profileResp = await axios.get<IProfile>('/users/me');
+    const isLoggedIn = profileResp.status === 404 || profileResp.status === 200;
+    return { profile: profileResp.data, isLoggedIn };
   };
 
   const register: RegisterQuery = async (data: ProfileData): Promise<any> => {
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 688f5ce..67ce166 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -142,7 +142,7 @@ const Header: React.FC<HeaderProps> = ({ customToolbar, menuItems = MENU_ITEMS }
                     />
                   ))}
 
-                  {profile.role === 'ADMIN' && (
+                  {profile.profile && profile.profile.role === 'ADMIN' && (
                     <>
                       {ADMIN_MENU_ITEMS.map((item) => (
                         <Tab
@@ -174,7 +174,7 @@ const Header: React.FC<HeaderProps> = ({ customToolbar, menuItems = MENU_ITEMS }
               </IconButton>
 
               <Typography variant="h6" align="center" className={classes.texts}>
-                {profile.name}
+                {profile.profile && profile.profile.name}
               </Typography>
               <a href="/api/v1/logout">
                 <Box color="secondary.main">
diff --git a/src/components/RememberMe.tsx b/src/components/RememberMe.tsx
index 7731549..d9e6dc4 100644
--- a/src/components/RememberMe.tsx
+++ b/src/components/RememberMe.tsx
@@ -1,4 +1,6 @@
+import { isNil } from 'lodash';
 import React, { useEffect } from 'react';
+import { Redirect } from 'react-router-dom';
 import useMe from '../hooks/useMe';
 import { useUserContext } from '../hooks/useUserContext';
 
@@ -16,6 +18,10 @@ const RememberMe: React.FC = ({ children }) => {
     }
   }, [me, setProfile]);
 
+  if (isNil(me?.profile) && me?.isLoggedIn) {
+    return <Redirect to="/register" />;
+  }
+
   return <>{children}</>;
 };
 
diff --git a/src/context/UserContext.tsx b/src/context/UserContext.tsx
index 99051b0..cac0b36 100644
--- a/src/context/UserContext.tsx
+++ b/src/context/UserContext.tsx
@@ -1,9 +1,14 @@
 import React, { createContext, useState } from 'react';
 import { IProfile } from '../types/Profile';
 
+export type ProfileWithStatus = {
+  profile?: IProfile;
+  isLoggedIn: boolean;
+};
+
 export interface UserContextType {
-  profile: IProfile | undefined;
-  setProfile: (profile: IProfile | undefined) => void;
+  profile?: ProfileWithStatus;
+  setProfile: (profile: ProfileWithStatus | undefined) => void;
 }
 
 /* // Context
@@ -24,7 +29,7 @@ export const UserContext = createContext({} as UserContextType);
 const { Provider } = UserContext;
 
 export const UserStateProvider: React.FC = ({ children }) => {
-  const [profile, setProfile] = useState<IProfile | undefined>();
+  const [profile, setProfile] = useState<ProfileWithStatus>();
 
   return <Provider value={{ profile, setProfile }}>{children}</Provider>;
 };
diff --git a/src/hooks/useMe.tsx b/src/hooks/useMe.tsx
index 2929427..c52226a 100644
--- a/src/hooks/useMe.tsx
+++ b/src/hooks/useMe.tsx
@@ -1,9 +1,9 @@
 import { useQuery, UseQueryResult } from 'react-query';
-import { IProfile } from '../types/Profile';
+import { ProfileWithStatus } from '../context';
 import useClientContext from './useClientContext';
 
-export default function useMe(): UseQueryResult<IProfile, Error> {
+export default function useMe(): UseQueryResult<ProfileWithStatus, Error> {
   const client = useClientContext();
 
-  return useQuery<IProfile, Error>('me', async () => client.client.auth.me());
+  return useQuery<ProfileWithStatus, Error>('me', async () => client.client.auth.me());
 }
-- 
GitLab