diff --git a/app/routes/_data.tsx b/app/routes/_data.tsx index 41ecd70..1f30d7f 100644 --- a/app/routes/_data.tsx +++ b/app/routes/_data.tsx @@ -3,7 +3,8 @@ import { type LoaderFunctionArgs, redirect } from '@remix-run/node' import { Outlet } from '@remix-run/react' import TabLink from '~/components/TabLink' -import { getSession } from '~/utils/sessions' +import { HeadscaleError, pull } from '~/utils/headscale' +import { destroySession, getSession } from '~/utils/sessions' export async function loader({ request }: LoaderFunctionArgs) { const session = await getSession(request.headers.get('Cookie')) @@ -11,6 +12,25 @@ export async function loader({ request }: LoaderFunctionArgs) { return redirect('/login') } + try { + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + await pull('v1/apikey', session.get('hsApiKey')!) + } catch (error) { + if (error instanceof HeadscaleError) { + console.error(error) + // Safest to just redirect to login if we can't pull + return redirect('/login', { + headers: { + // eslint-disable-next-line @typescript-eslint/naming-convention + 'Set-Cookie': await destroySession(session) + } + }) + } + + // Otherwise propagate to boundary + throw error + } + // eslint-disable-next-line unicorn/no-null return null } diff --git a/app/utils/headscale.ts b/app/utils/headscale.ts index 1c6e615..d7e1e2f 100644 --- a/app/utils/headscale.ts +++ b/app/utils/headscale.ts @@ -1,3 +1,13 @@ +export class HeadscaleError extends Error { + status: number + + constructor(message: string, status: number) { + super(message) + this.name = 'HeadscaleError' + this.status = status + } +} + /* eslint-disable @typescript-eslint/no-non-null-assertion */ export async function pull(url: string, key: string) { const prefix = process.env.HEADSCALE_URL! @@ -8,7 +18,7 @@ export async function pull(url: string, key: string) { }) if (!response.ok) { - throw new Error(response.statusText) + throw new HeadscaleError(await response.text(), response.status) } return response.json() as Promise @@ -25,7 +35,7 @@ export async function post(url: string, key: string, body?: unknown) { }) if (!response.ok) { - throw new Error(await response.text()) + throw new HeadscaleError(await response.text(), response.status) } return response.json() as Promise