import { getSetting } from '@/lib/db'; import { corsJson, corsPreflight } from '../cors'; /** The extension's 2FA lookup. It knows the tab's host; this dashboard knows * which person it is (the master-issued `instance_id`) and where the master * is, so it asks the master for this person's codes on that site and passes * them through. * * Never an error status: no link to the master, or a master that can't be * reached, is just "no codes" with a reason — the extension shows nothing. */ export async function GET(request: Request) { const host = new URL(request.url).searchParams.get('host')?.trim().toLowerCase(); if (!host) return corsJson({ codes: [], reason: 'host is required' }); const master = getSetting('master_dashboard_url')?.trim().replace(/\/+$/, ''); const person = getSetting('instance_id')?.trim(); if (!master || !person) return corsJson({ codes: [], reason: 'not linked to master' }); const url = `${master}/api/otp?person=${encodeURIComponent(person)}&host=${encodeURIComponent(host)}`; try { const res = await fetch(url, { cache: 'no-store', signal: AbortSignal.timeout(5000) }); if (!res.ok) return corsJson({ codes: [], reason: `master answered ${res.status}` }); const data = (await res.json()) as { codes?: unknown[]; serverTime?: number; scope?: string }; // A master from before per-person lookups ignores ?person= and answers // with every stored code — never show those. if (data.scope !== 'person') return corsJson({ codes: [], reason: 'master is too old for 2FA lookups' }); return corsJson({ codes: data.codes ?? [], serverTime: data.serverTime ?? Date.now() }); } catch (err) { return corsJson({ codes: [], reason: `master unreachable: ${(err as Error).message}` }); } } export async function OPTIONS() { return corsPreflight(); }