From 99583e4c412be9831719c3be93fd651e5d7b95ae Mon Sep 17 00:00:00 2001 From: rd-code-23 Date: Fri, 21 Aug 2026 17:29:46 -0700 Subject: [PATCH] feat(auth): add guest dashboard entry --- .../auth/google/google-oidc.routes.test.ts | 10 ++++++- .../api/src/auth/google/google-oidc.routes.ts | 2 +- .../src/features/auth/guest-session.test.ts | 19 ++++++++++++ apps/web/src/features/auth/guest-session.ts | 10 +++++++ apps/web/src/features/auth/welcome-page.tsx | 10 +++++++ .../features/dashboard/dashboard-landing.tsx | 16 ++++++++++ apps/web/src/routeTree.gen.ts | 24 +++++++++++++-- apps/web/src/routes/dashboard.tsx | 8 +++++ apps/web/src/routes/index.test.tsx | 29 +++++++++++++++++-- apps/web/src/routes/index.tsx | 6 +++- 10 files changed, 125 insertions(+), 9 deletions(-) create mode 100644 apps/web/src/features/auth/guest-session.test.ts create mode 100644 apps/web/src/features/auth/guest-session.ts create mode 100644 apps/web/src/features/dashboard/dashboard-landing.tsx create mode 100644 apps/web/src/routes/dashboard.tsx diff --git a/apps/api/src/auth/google/google-oidc.routes.test.ts b/apps/api/src/auth/google/google-oidc.routes.test.ts index d976f4a..4b7804c 100644 --- a/apps/api/src/auth/google/google-oidc.routes.test.ts +++ b/apps/api/src/auth/google/google-oidc.routes.test.ts @@ -140,6 +140,14 @@ describe('GET /auth/google', () => { expect(secondFlow.nonce).not.toBe(firstFlow.nonce); expect(secondFlow.codeVerifier).not.toBe(firstFlow.codeVerifier); }); + + it('returns successful logins to the dashboard by default', async () => { + const { app, store } = createTestContext(); + + await request(app).get('/auth/google'); + + expect(readStoredFlow(store).returnTo).toBe('/dashboard'); + }); }); describe('validateReturnTo', () => { @@ -152,7 +160,7 @@ describe('validateReturnTo', () => { 'javascript:alert(1)', '/path%00suffix', ])('rejects unsafe destination %s', (destination) => { - expect(validateReturnTo(destination)).toBe('/'); + expect(validateReturnTo(destination)).toBe('/dashboard'); }); it('accepts a root-relative application destination', () => { diff --git a/apps/api/src/auth/google/google-oidc.routes.ts b/apps/api/src/auth/google/google-oidc.routes.ts index c4011f1..ed8f146 100644 --- a/apps/api/src/auth/google/google-oidc.routes.ts +++ b/apps/api/src/auth/google/google-oidc.routes.ts @@ -16,7 +16,7 @@ import type { Env } from '../../config/env-schema.js'; import type { GoogleUserProfile } from './google-user.service.js'; const GOOGLE_ISSUER = new URL('https://accounts.google.com'); -const DEFAULT_RETURN_PATH = '/'; +const DEFAULT_RETURN_PATH = '/dashboard'; const OIDC_FLOW_LIFETIME_MS = 10 * 60 * 1000; const googleIdentitySchema = z.object({ diff --git a/apps/web/src/features/auth/guest-session.test.ts b/apps/web/src/features/auth/guest-session.test.ts new file mode 100644 index 0000000..b739cd2 --- /dev/null +++ b/apps/web/src/features/auth/guest-session.test.ts @@ -0,0 +1,19 @@ +// Verifies the temporary guest marker can be started and cleared by the welcome flow. +import { afterEach, describe, expect, it } from 'vitest'; + +import { clearGuestSession, startGuestSession } from './guest-session'; + +afterEach(() => { + sessionStorage.clear(); +}); + +describe('guest session', () => { + it('can clear guest mode when the welcome page loads', () => { + startGuestSession(); + expect(sessionStorage.getItem('goforlift.guest')).toBe('true'); + + clearGuestSession(); + + expect(sessionStorage.getItem('goforlift.guest')).toBeNull(); + }); +}); diff --git a/apps/web/src/features/auth/guest-session.ts b/apps/web/src/features/auth/guest-session.ts new file mode 100644 index 0000000..107a8b0 --- /dev/null +++ b/apps/web/src/features/auth/guest-session.ts @@ -0,0 +1,10 @@ +// Stores the temporary browser-tab marker used to identify guest mode. +const GUEST_SESSION_KEY = 'goforlift.guest'; + +export function startGuestSession() { + sessionStorage.setItem(GUEST_SESSION_KEY, 'true'); +} + +export function clearGuestSession() { + sessionStorage.removeItem(GUEST_SESSION_KEY); +} diff --git a/apps/web/src/features/auth/welcome-page.tsx b/apps/web/src/features/auth/welcome-page.tsx index aec0871..2628936 100644 --- a/apps/web/src/features/auth/welcome-page.tsx +++ b/apps/web/src/features/auth/welcome-page.tsx @@ -1,4 +1,5 @@ // Presents the responsive welcome page and entry points for Google sign-in and guest access. +import { useNavigate } from '@tanstack/react-router'; import { UserRound } from 'lucide-react'; import shipUrl from '../../assets/goforlift-ship.png'; @@ -7,8 +8,16 @@ import desktopStarfieldUrl from '../../assets/welcome-starfield-desktop.webp'; import starfieldUrl from '../../assets/welcome-starfield.webp'; import wordmarkUrl from '../../assets/goforlift-wordmark.png'; import { Button } from '../../components/ui/button'; +import { startGuestSession } from './guest-session'; export function WelcomePage() { + const navigate = useNavigate(); + + function continueAsGuest() { + startGuestSession(); + void navigate({ to: '/dashboard' }); + } + return (