From 5e4f519c83b2f2087b00c808bb9e1d3372f77e24 Mon Sep 17 00:00:00 2001 From: Igor Loskutov Date: Tue, 2 Sep 2025 19:12:04 -0400 Subject: [PATCH] compile fix --- www/app/(app)/browse/page.tsx | 1 - www/app/(app)/transcripts/shareAndPrivacy.tsx | 5 ++-- www/app/[roomName]/page.tsx | 4 ++- www/app/lib/AuthProvider.tsx | 8 ++++-- www/app/lib/auth.ts | 3 +-- www/app/lib/types.ts | 25 +++++++++++++++++++ www/app/lib/useUserId.ts | 19 -------------- 7 files changed, 38 insertions(+), 27 deletions(-) delete mode 100644 www/app/lib/useUserId.ts diff --git a/www/app/(app)/browse/page.tsx b/www/app/(app)/browse/page.tsx index 2a22ae9c..8523650e 100644 --- a/www/app/(app)/browse/page.tsx +++ b/www/app/(app)/browse/page.tsx @@ -19,7 +19,6 @@ import { parseAsStringLiteral, } from "nuqs"; import { LuX } from "react-icons/lu"; -import useSessionUser from "../../lib/useUserId"; import type { components } from "../../reflector-api"; type Room = components["schemas"]["Room"]; diff --git a/www/app/(app)/transcripts/shareAndPrivacy.tsx b/www/app/(app)/transcripts/shareAndPrivacy.tsx index 608ebb1a..a53c93e3 100644 --- a/www/app/(app)/transcripts/shareAndPrivacy.tsx +++ b/www/app/(app)/transcripts/shareAndPrivacy.tsx @@ -22,7 +22,7 @@ import { useTranscriptUpdate } from "../../lib/apiHooks"; import ShareLink from "./shareLink"; import ShareCopy from "./shareCopy"; import ShareZulip from "./shareZulip"; -import useUserId from "../../lib/useUserId"; +import { useAuth } from "../../lib/AuthProvider"; type ShareAndPrivacyProps = { finalSummaryRef: any; @@ -85,7 +85,8 @@ export default function ShareAndPrivacy(props: ShareAndPrivacyProps) { } }; - const userId = useUserId(); + const auth = useAuth(); + const userId = auth.status === "authenticated" ? auth.user?.id : null; useEffect(() => { setIsOwner(!!(requireLogin && userId === props.transcriptResponse.user_id)); diff --git a/www/app/[roomName]/page.tsx b/www/app/[roomName]/page.tsx index 3b51f4d5..c4638cbb 100644 --- a/www/app/[roomName]/page.tsx +++ b/www/app/[roomName]/page.tsx @@ -260,7 +260,9 @@ export default function Room(details: RoomDetails) { const roomName = details.params.roomName; const meeting = useRoomMeeting(roomName); const router = useRouter(); - const { isLoading, isAuthenticated } = useSessionStatus(); + const status = useSessionStatus(); + const isAuthenticated = status === "authenticated"; + const isLoading = status === "loading" || meeting.loading; const roomUrl = meeting?.response?.host_room_url ? meeting?.response?.host_room_url diff --git a/www/app/lib/AuthProvider.tsx b/www/app/lib/AuthProvider.tsx index c9b47914..84449c35 100644 --- a/www/app/lib/AuthProvider.tsx +++ b/www/app/lib/AuthProvider.tsx @@ -3,7 +3,11 @@ import { createContext, useContext, useEffect } from "react"; import { useSession as useNextAuthSession } from "next-auth/react"; import { configureApiAuth } from "./apiClient"; -import { assertExtendedToken, CustomSession } from "./types"; +import { + assertExtendedToken, + assertExtendedTokenAndUserId, + CustomSession, +} from "./types"; type AuthContextType = | { status: "loading" } @@ -19,7 +23,7 @@ const AuthContext = createContext(undefined); export function AuthProvider({ children }: { children: React.ReactNode }) { const { data: session, status } = useNextAuthSession(); - const customSession = session ? assertExtendedToken(session) : null; + const customSession = session ? assertExtendedTokenAndUserId(session) : null; const contextValue: AuthContextType = status === "loading" diff --git a/www/app/lib/auth.ts b/www/app/lib/auth.ts index 859459d3..fea903aa 100644 --- a/www/app/lib/auth.ts +++ b/www/app/lib/auth.ts @@ -83,7 +83,6 @@ export const authOptions: AuthOptions = { return await lockedRefreshAccessToken(token); }, async session({ session, token }) { - // TODO no as const extendedToken = token as JWTWithAccessToken; return { ...session, @@ -91,7 +90,7 @@ export const authOptions: AuthOptions = { accessTokenExpires: extendedToken.accessTokenExpires, error: extendedToken.error, user: { - id: extendedToken.sub, + id: assertExists(extendedToken.sub), name: extendedToken.name, email: extendedToken.email, }, diff --git a/www/app/lib/types.ts b/www/app/lib/types.ts index 70f58ec5..d9b48a41 100644 --- a/www/app/lib/types.ts +++ b/www/app/lib/types.ts @@ -13,6 +13,9 @@ export interface CustomSession extends Session { accessToken: string; accessTokenExpires: number; error?: string; + user: Session["user"] & { + id: string; + }; } // assumption that JWT is JWTWithAccessToken - not ideal, TODO find a reason we have to do that @@ -39,3 +42,25 @@ export const assertExtendedToken = ( } throw new Error("Token is not extended with access token"); }; + +export const assertExtendedTokenAndUserId = ( + t: T, +): T & { + accessTokenExpires: number; + accessToken: string; + user: U & { + id: string; + }; +} => { + const extendedToken = assertExtendedToken(t); + if (typeof (extendedToken.user as any)?.id === "string") { + return t as T & { + accessTokenExpires: number; + accessToken: string; + user: U & { + id: string; + }; + }; + } + throw new Error("Token is not extended with user id"); +}; diff --git a/www/app/lib/useUserId.ts b/www/app/lib/useUserId.ts deleted file mode 100644 index 415195b3..00000000 --- a/www/app/lib/useUserId.ts +++ /dev/null @@ -1,19 +0,0 @@ -"use client"; - -import { useState, useEffect } from "react"; -import { useSession as useNextAuthSession } from "next-auth/react"; -import { Session } from "next-auth"; -import { useAuth } from "./AuthProvider"; - -const assertUserId = (u: T): T & { id: string } => { - if (typeof (u as { id: string }).id !== "string") - throw new Error("Expected user.id to be a string"); - return u as T & { id: string }; -}; - -// the current assumption in useSessionUser is that "useNextAuthSession" also returns user.id, although useNextAuthSession documentation states it doesn't -// the hook is to isolate the potential impact and to document this behaviour -export default function useUserId() { - const auth = useAuth(); - return auth.status === "authenticated" ? assertUserId(auth.user) : null; -}