diff --git a/src/components/Auth/index.tsx b/src/components/Auth/index.tsx index 43976edc..272d40b9 100644 --- a/src/components/Auth/index.tsx +++ b/src/components/Auth/index.tsx @@ -1,3 +1,6 @@ +// TODO: This can now be deleted +// the cookie handling should be done in AuthProvider +// and project resolution in the ProjectProvider 'use client'; import { routes } from '@fleek-platform/utils-routes'; @@ -5,7 +8,6 @@ import { useEffect, useState } from 'react'; import { useRouter } from 'next/navigation'; import { constants } from '../../constants'; import { matchesPathname } from '../../utils/matchesPathname'; -import { FleekLogo } from '../FleekLogo/FleekLogo'; import type { FC, ReactNode } from 'react'; @@ -18,26 +20,47 @@ export const Auth: FC = ({ children }) => { const [isChecking, setIsChecking] = useState(true); useEffect(() => { + console.log('[debug] Auth: useEffect: deps router: 1'); + const checkAuth = () => { + console.log('[debug] Auth: checkAuth: 1'); + setIsChecking(true); + const authToken = document.cookie .split('; ') .find((row) => row.startsWith('authProviderToken=')) ?.split('=')[1]; + const projectId = document.cookie .split('; ') .find((row) => row.startsWith('projectId=')) - ?.split('=')[1] || constants.DEFAULT_PROJECT_ID; + ?.split('=')[1]; + + console.log(`[debug] Auth: checkAuth: ${JSON.stringify({ + authToken, + projectId, + })}`); + const hasAuthentication = Boolean(authToken); const currentPath = window.location.pathname; + console.log(`[debug] Auth: checkAuth: ${JSON.stringify({ + hasAuthentication, + currentPath, + })}`); + if (hasAuthentication && currentPath === routes.home()) { - router.push(routes.project.home({ projectId })); + console.log(`[debug] Auth: checkAuth: hasAuth and is path home`); + router.push(routes.project.home({ projectId })); setIsChecking(false); + return; } + // TODO: The dashboard should not have public routes + // it's membership only const isPublicRoute = Boolean( constants.PUBLIC_ROUTES.find((route) => matchesPathname(route, currentPath), diff --git a/src/components/ftw/RootLayout/RootLayout.tsx b/src/components/ftw/RootLayout/RootLayout.tsx index 721bb6ee..5fd11e98 100644 --- a/src/components/ftw/RootLayout/RootLayout.tsx +++ b/src/components/ftw/RootLayout/RootLayout.tsx @@ -170,6 +170,8 @@ const Sidebar: React.FC = ({ // on the client side, show versions if not prod or user is internal if ( !isServerSide() && + // TODO: This shouldn't be hard-typed + // e.g. staging vs prd URLs (location.hostname !== 'app.fleek.xyz' || flags.isInternalUser) ) { setShowVersion(true); diff --git a/src/fragments/App/Navbar/NavbarCombined.tsx b/src/fragments/App/Navbar/NavbarCombined.tsx index 5b32f26c..96d685cb 100644 --- a/src/fragments/App/Navbar/NavbarCombined.tsx +++ b/src/fragments/App/Navbar/NavbarCombined.tsx @@ -4,9 +4,9 @@ import { NavbarProject } from './NavbarProject'; import { NavbarUnauthenticated } from './NavbarUnauthenticated'; export const NavbarCombined: React.FC = () => { - const session = useSessionContext(true); + const { loading, auth: { accessToken } } = useSessionContext(true); - if (session.loading || session.auth.token) { + if (loading || accessToken) { return ; } diff --git a/src/fragments/IpfsPropagation/Layout.tsx b/src/fragments/IpfsPropagation/Layout.tsx index 9d74e69c..be6c3f86 100644 --- a/src/fragments/IpfsPropagation/Layout.tsx +++ b/src/fragments/IpfsPropagation/Layout.tsx @@ -15,10 +15,10 @@ import { App } from '../App/App'; export const IpfsPropagationLayout: React.FC = ({ children, }) => { - const session = useSessionContext(); + const { loading, auth: { accessToken }} = useSessionContext(); const navItems = useMainNavigationItems(); - if (!session.auth.token) { + if (!accessToken) { return ( <> @@ -42,7 +42,7 @@ export const IpfsPropagationLayout: React.FC = ({ } - isNavigationLoading={session.loading} + isNavigationLoading={loading} navigation={navItems} breadcrumbs={breadcrumbs} > @@ -53,9 +53,9 @@ export const IpfsPropagationLayout: React.FC = ({ }; const Content: React.FC = ({ children }) => { - const session = useSessionContext(); + const { auth: { accessToken } } = useSessionContext(); - if (session.auth.token) { + if (accessToken) { return {children}; } diff --git a/src/fragments/IpfsPropagation/Sections/CreateGatewayButton.tsx b/src/fragments/IpfsPropagation/Sections/CreateGatewayButton.tsx index 0c3a2218..81f4f7c7 100644 --- a/src/fragments/IpfsPropagation/Sections/CreateGatewayButton.tsx +++ b/src/fragments/IpfsPropagation/Sections/CreateGatewayButton.tsx @@ -5,13 +5,13 @@ import { ActionBox } from '@/components'; import { useSessionContext } from '@/providers/SessionProvider'; export const CreateGatewayButton: React.FC = () => { - const session = useSessionContext(); + const { auth: { accessToken, login } } = useSessionContext(); - const hasToken = Boolean(session.auth.token); + const hasToken = Boolean(accessToken); const handleClick = () => { if (!hasToken) { - session.auth.login( + login( 'dynamic', routes.project.settings.privateGateways({ projectId: 'project' }), ); diff --git a/src/fragments/Migration/Layout.tsx b/src/fragments/Migration/Layout.tsx index ab23e93a..d88d433d 100644 --- a/src/fragments/Migration/Layout.tsx +++ b/src/fragments/Migration/Layout.tsx @@ -13,11 +13,11 @@ export type Layout = React.PropsWithChildren<{ }>; export const Layout: React.FC = ({ children }) => { - const session = useSessionContext(); + const { error, auth: { login, accessToken }, loading } = useSessionContext(); const handleLogIn = () => { - if (!session.error && !session.loading && !session.auth.token) { - session.auth.login('dynamic', routes.migration()); + if (!error && !loading && !accessToken) { + login('dynamic', routes.migration()); } }; @@ -26,7 +26,7 @@ export const Layout: React.FC = ({ children }) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - if (session.auth.token) { + if (accessToken) { return ( <> diff --git a/src/fragments/Migration/Steps/Step1.tsx b/src/fragments/Migration/Steps/Step1.tsx index 216605a4..20c65818 100644 --- a/src/fragments/Migration/Steps/Step1.tsx +++ b/src/fragments/Migration/Steps/Step1.tsx @@ -6,7 +6,7 @@ import { useMigrationContext } from '../Migration.context'; import { MigrationStyles as S } from '../Migration.styles'; export const Step1: React.FC = () => { - const session = useSessionContext(); + const { auth: { accessToken } } = useSessionContext(); const { isStep1Loading: isLoading, handleBeginMigration, @@ -14,7 +14,7 @@ export const Step1: React.FC = () => { migrationToken, } = useMigrationContext(); - const isDisabled = !session.auth.token || isLoading || !migrationToken; + const isDisabled = !accessToken || isLoading || !migrationToken; return ( diff --git a/src/fragments/Projects/Layout.tsx b/src/fragments/Projects/Layout.tsx index 34bb7575..f91808dc 100644 --- a/src/fragments/Projects/Layout.tsx +++ b/src/fragments/Projects/Layout.tsx @@ -1,3 +1,4 @@ +import { useMemo, memo } from 'react'; import { ProjectDropdown, RootLayout } from '@/components'; import { useMainNavigationItems } from '@/hooks/useMainNavigationItems'; import { useSessionContext } from '@/providers/SessionProvider'; @@ -6,9 +7,17 @@ export type Layout = React.PropsWithChildren<{ nav?: React.ReactNode | React.ReactNode[]; }>; +// TODO: When clicking outside the menu, e.g. right side +// content area, this component re-renders. Why? export const Layout: React.FC = ({ children, nav: pageNavContent }) => { const session = useSessionContext(true); - const navigation = useMainNavigationItems(); + const navigationItems = useMainNavigationItems(); + // TODO: The memo won't be effective as the nav items + // has the URL attribute which includes diff projectid + // per navigation selection + const navigation = useMemo(() => navigationItems, [navigationItems]); + + console.log('[debug] Layout: re-render: 1', JSON.stringify(navigation)) return ( @@ -26,3 +35,5 @@ export const Layout: React.FC = ({ children, nav: pageNavContent }) => { ); }; + +Layout.displayName = 'Layout'; diff --git a/src/fragments/Template/List/Hero/Hero.tsx b/src/fragments/Template/List/Hero/Hero.tsx index d5977643..2f341fb5 100644 --- a/src/fragments/Template/List/Hero/Hero.tsx +++ b/src/fragments/Template/List/Hero/Hero.tsx @@ -36,12 +36,12 @@ export const Hero: React.FC = () => { }; const SubmitTemplateButton: React.FC = () => { - const session = useSessionContext(); + const { auth: { accessToken, login } } = useSessionContext(); const router = useRouter(); const handleSubmitTemplate = () => { - if (!session.auth.token) { - return session.auth.login('dynamic', routes.profile.settings.templates()); + if (!accessToken) { + return login('dynamic', routes.profile.settings.templates()); } return router.push(routes.profile.settings.templates()); diff --git a/src/hooks/useAuthCookie.ts b/src/hooks/useAuthCookie.ts index 07bd412e..32867b4c 100644 --- a/src/hooks/useAuthCookie.ts +++ b/src/hooks/useAuthCookie.ts @@ -16,7 +16,7 @@ export const useAuthCookie = (): [ const set = (jwt: string) => { try { - const parsed = decodeAccessToken({ token: jwt }); + const parsed = decodeAccessToken({ accessToken: jwt }); cookies.set(key, jwt, { expires: DateTime.fromSeconds(parsed.exp).toJSDate(), diff --git a/src/hooks/useAuthProviders.ts b/src/hooks/useAuthProviders.ts index a23c240e..22799a22 100644 --- a/src/hooks/useAuthProviders.ts +++ b/src/hooks/useAuthProviders.ts @@ -8,9 +8,9 @@ export type AuthProviders = 'dynamic'; export type AuthWith = { handleLogin: () => void; - handleLogout: () => void; + handleLogout: () => Promise; requestAccessToken: (projectId?: string) => Promise; - token: string | undefined; + authProviderToken?: string; }; export const useAuthProviders = (): Record => { @@ -29,10 +29,13 @@ const useAuthWithDynamic = (): AuthWith => { const handleLogin = () => dynamic.setShowAuthFlow(true); - const handleLogout = () => dynamic.handleLogOut(); + const handleLogout = async () => dynamic.handleLogOut(); const requestAccessToken = async (projectId?: string): Promise => { + console.log('[debug] useAuthProvidders: requestAccessToken: 1') if (!dynamic.authToken) { + console.log('[debug] useAuthProvidders: requestAccessToken: requestAccessToken NOT') + return ''; } @@ -40,6 +43,8 @@ const useAuthWithDynamic = (): AuthWith => { data: { authToken: dynamic.authToken, projectId }, }); + console.log(`[debug] useAuthProvidders: requestAccessToken: loginWithDynamic: response: ${JSON.stringify(data)}`) + if (data && data.loginWithDynamic) { return data.loginWithDynamic; } @@ -51,7 +56,7 @@ const useAuthWithDynamic = (): AuthWith => { handleLogin, handleLogout, requestAccessToken, - token: dynamic.authToken, + authProviderToken: dynamic.authToken, }; }; @@ -61,8 +66,8 @@ const getMockedProvider: () => AuthWith = () => { return { handleLogin: () => {}, - handleLogout: () => {}, + handleLogout: async () => {}, requestAccessToken: async () => 'mocked-token', - token: cookies.values.authProviderToken, + accessToken: cookies.values.authProviderToken, }; }; diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index 09f540cf..285b0628 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -51,12 +51,10 @@ const App = ({ Component, pageProps, requestCookies }: AppProps) => { )} - -

{noCanonical}

- {getLayout()} - - -
+

{noCanonical}

+ {getLayout()} + +
); diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 262bf578..d19cbafd 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -5,18 +5,18 @@ import { useSessionContext } from '@/providers/SessionProvider'; import { Page } from '@/types/App'; const HomePage: Page = () => { - const session = useSessionContext(); + const { error, loading, auth: { accessToken, login } } = useSessionContext(); const handleLogIn = () => { - if (!session.error && !session.loading && !session.auth.token) { - session.auth.login('dynamic'); + if (!error && !loading && !accessToken) { + login('dynamic'); } }; useEffect(() => { handleLogIn(); // eslint-disable-next-line react-hooks/exhaustive-deps - }, [session.loading]); + }, [loading]); return ( <> diff --git a/src/pages/login/[verificationSessionId].tsx b/src/pages/login/[verificationSessionId].tsx index 0564b4ad..886f469f 100644 --- a/src/pages/login/[verificationSessionId].tsx +++ b/src/pages/login/[verificationSessionId].tsx @@ -13,7 +13,7 @@ import { Log } from '@/utils/log'; const LoginWithSessionPage: Page = () => { const router = useRouter(); - const session = useSessionContext(); + const { auth: { accessToken, login }, project, loading } = useSessionContext(); const [ createLoginVerificationSessionMutation, @@ -26,9 +26,9 @@ const LoginWithSessionPage: Page = () => { const handleRedirect = useCallback(() => { return router.replace( - routes.project.home({ projectId: session.project.id }), + routes.project.home({ projectId: project.id }), ); - }, [router, session.project.id]); + }, [router, project.id]); const handleCreateVerificationSession = useCallback(async () => { try { @@ -76,7 +76,7 @@ const LoginWithSessionPage: Page = () => { } if ( - session.auth.token && + accessToken && !createLoginVerificationSessionMutation?.data ?.createLoginVerificationSession ) { @@ -106,8 +106,8 @@ const LoginWithSessionPage: Page = () => { withExternalLink >