diff --git a/app/_components/FeatureComponents/Sidebar/Parts/SharedItemsList.tsx b/app/_components/FeatureComponents/Sidebar/Parts/SharedItemsList.tsx index 0e39f408..1d1d3cf0 100644 --- a/app/_components/FeatureComponents/Sidebar/Parts/SharedItemsList.tsx +++ b/app/_components/FeatureComponents/Sidebar/Parts/SharedItemsList.tsx @@ -167,6 +167,7 @@ export const SharedItemsList = ({ handleItemClick(e, fullItem)} data-sidebar-item-selected={isSelected} className={cn( diff --git a/app/_components/FeatureComponents/Sidebar/Parts/SidebarItem.tsx b/app/_components/FeatureComponents/Sidebar/Parts/SidebarItem.tsx index 7f59fc74..ea959380 100644 --- a/app/_components/FeatureComponents/Sidebar/Parts/SidebarItem.tsx +++ b/app/_components/FeatureComponents/Sidebar/Parts/SidebarItem.tsx @@ -202,6 +202,7 @@ export const SidebarItem = ({
{ const router = useRouter(); + const { user } = useAppMode(); const [isConnected, setIsConnected] = useState(false); const wsRef = useRef(null); const connectionIdRef = useRef(null); @@ -70,6 +72,7 @@ export const WebSocketProvider = ({ children }: { children: ReactNode }) => { const connect = useCallback(() => { if (!mountedRef.current) return; + if (!user) return; if (wsRef.current?.readyState === WebSocket.OPEN) return; const isDev = process.env.NODE_ENV === "development"; @@ -111,7 +114,7 @@ export const WebSocketProvider = ({ children }: { children: ReactNode }) => { }; wsRef.current = ws; - }, [handleMessage]); + }, [handleMessage, user]); useEffect(() => { mountedRef.current = true; diff --git a/app/api/serwist/[path]/route.ts b/app/api/serwist/[path]/route.ts index b192063b..a8e737f8 100644 --- a/app/api/serwist/[path]/route.ts +++ b/app/api/serwist/[path]/route.ts @@ -1,15 +1,10 @@ -import { spawnSync } from "node:child_process"; import { createSerwistRoute } from "@serwist/turbopack"; -const revision = spawnSync("git", ["rev-parse", "HEAD"], { - encoding: "utf-8", -}).stdout?.trim() ?? crypto.randomUUID(); - export const { dynamic, dynamicParams, revalidate, generateStaticParams, GET } = createSerwistRoute({ - additionalPrecacheEntries: [{ url: "/~offline", revision }], swSrc: "app/sw.ts", useNativeEsbuild: true, nextConfig: {}, maximumFileSizeToCacheInBytes: 6 * 1024 * 1024, + globIgnores: ["flags/**"], }); diff --git a/package.json b/package.json index c1e34799..908319f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "jotty.page", - "version": "1.21.0", + "version": "1.21.1", "private": true, "scripts": { "dev": "next dev", diff --git a/proxy.ts b/proxy.ts index 88c76218..56e56c86 100644 --- a/proxy.ts +++ b/proxy.ts @@ -4,6 +4,43 @@ import { isEnvEnabled, isDebugFlag } from "./app/_utils/env-utils"; const debugProxy = isDebugFlag("proxy"); +const SESSION_CACHE_TTL = 10_000; +const sessionCache = new Map(); + +const _checkSession = async (sessionId: string, internalApiUrl: string, cookie: string) => { + const cached = sessionCache.get(sessionId); + if (cached && Date.now() - cached.ts < SESSION_CACHE_TTL) return cached.valid; + + const sessionCheckUrl = new URL(`${internalApiUrl}/api/auth/check-session`); + + if (debugProxy) { + console.log("MIDDLEWARE - Session Check URL:", sessionCheckUrl.href); + } + + const res = await fetch(sessionCheckUrl, { + headers: { Cookie: cookie }, + cache: "no-store", + }); + + if (debugProxy) { + console.log("MIDDLEWARE - Session Check Response:"); + console.log(" status:", res.status); + console.log(" statusText:", res.statusText); + console.log(" ok:", res.ok); + } + + sessionCache.set(sessionId, { valid: res.ok, ts: Date.now() }); + + if (sessionCache.size > 1000) { + const now = Date.now(); + sessionCache.forEach((val, key) => { + if (now - val.ts > SESSION_CACHE_TTL) sessionCache.delete(key); + }); + } + + return res.ok; +}; + export const proxy = async (request: NextRequest) => { const { pathname } = request.nextUrl; @@ -61,27 +98,13 @@ export const proxy = async (request: NextRequest) => { console.log(" → Using:", internalApiUrl); } - const sessionCheckUrl = new URL(`${internalApiUrl}/api/auth/check-session`); - - if (debugProxy) { - console.log("MIDDLEWARE - Session Check URL:", sessionCheckUrl.href); - } - - const sessionCheck = await fetch(sessionCheckUrl, { - headers: { - Cookie: request.headers.get("Cookie") || "", - }, - cache: "no-store", - }); - - if (debugProxy) { - console.log("MIDDLEWARE - Session Check Response:"); - console.log(" status:", sessionCheck.status); - console.log(" statusText:", sessionCheck.statusText); - console.log(" ok:", sessionCheck.ok); - } + const valid = await _checkSession( + sessionId, + internalApiUrl, + request.headers.get("Cookie") || "", + ); - if (!sessionCheck.ok) { + if (!valid) { const redirectResponse = NextResponse.redirect(loginUrl); redirectResponse.cookies.delete(cookieName); @@ -102,6 +125,6 @@ export const proxy = async (request: NextRequest) => { export const config = { matcher: [ - "/((?!_next/static|_next/image|favicon.ico|site.webmanifest|sw.js|app-icons).*)", + "/((?!_next/static|_next/image|favicon.ico|site.webmanifest|sw.js|app-icons|app-screenshots|flags|fonts|images|repo-images|themes|openapi.yaml).*)", ], };