diff --git a/components/Dashboard/FormPane.tsx b/components/Dashboard/FormPane.tsx index e54bf634..af69f432 100644 --- a/components/Dashboard/FormPane.tsx +++ b/components/Dashboard/FormPane.tsx @@ -43,7 +43,6 @@ const actionButtons = [ const FormPane: React.FC = () => { const { project } = useSelectedProject() const { forms } = useListForms(project?.id) - const router = useRouter() const [selectedRow, setSelectedRow] = useState(false) diff --git a/components/ProtectedRoute.tsx b/components/ProtectedRoute.tsx new file mode 100644 index 00000000..57b8a78f --- /dev/null +++ b/components/ProtectedRoute.tsx @@ -0,0 +1,31 @@ +import { useAuth } from '@/context/Authentication' +import { useRouter } from 'next/router' +import { useEffect, ReactNode } from 'react' + +interface ProtectedRouteProps { + children?: ReactNode +} + +const ProtectedRoute: React.FC = ({ children }) => { + const { isAuthenticated } = useAuth() + const router = useRouter() + + useEffect(() => { + async function checkAuth() { + if ( + router.pathname !== '/__app/signin' && + router.pathname !== '/__app/signup' && + isAuthenticated && + !(await isAuthenticated()) + ) { + router.push('/signin') + } + } + + checkAuth() + }, [isAuthenticated, router]) + + return <>{children} +} + +export default ProtectedRoute diff --git a/context/Authentication.tsx b/context/Authentication.tsx index 894cd00c..9bea0754 100644 --- a/context/Authentication.tsx +++ b/context/Authentication.tsx @@ -4,7 +4,10 @@ import { useQueryClient } from '@tanstack/react-query' import { graphqlClient } from '@/api' import { CreateUserData } from '@/gql/graphql' -import { signinWithEmailAndPasswordQuery } from '@/graphql/queries/user' +import { + getSessionUserQuery, + signinWithEmailAndPasswordQuery, +} from '@/graphql/queries/user' import { useCreateUser } from '@/hooks/mutation/user' interface AuthenticationProviderProps { @@ -18,6 +21,7 @@ interface IAuthenticationContext { }) => Promise signOut?: () => Promise createUserWithEmailPassword?: (data: CreateUserData) => Promise + isAuthenticated?: () => Promise } const defaultContextValues: IAuthenticationContext = {} @@ -74,12 +78,33 @@ export const AuthenticationProvider: React.FC = ( router.push('/signin') }, [queryClient, isClient, router]) + const isAuthenticated: IAuthenticationContext['isAuthenticated'] = + async () => { + const token = localStorage.getItem('__authentication_token__') + if (!token) { + return false + } + + const loggedInUser = await graphqlClient + .request(getSessionUserQuery, {}) + .catch((error) => { + console.log(error.message) + }) + + if (!loggedInUser?.getSessionUser) { + return false + } + + return true + } + return ( {children} diff --git a/pages/_app.tsx b/pages/_app.tsx index 81aadb77..a9e3b8f9 100644 --- a/pages/_app.tsx +++ b/pages/_app.tsx @@ -8,6 +8,7 @@ import { Toaster } from 'react-hot-toast' import { AuthenticationProvider } from '@/context/Authentication' import '@/styles/globals.css' import ModalWrapper from '@/wrappers/ModalWrapper' +import ProtectedRoute from '@/components/ProtectedRoute' const queryClient = new QueryClient({ defaultOptions: { @@ -37,9 +38,11 @@ export default function App({ Component, pageProps }: AppProps) { defaultTheme="system" enableSystem > - - - + + + + +