otterdrive auth login in your terminal, then approve the sign-in in
+ your browser with your Otter Account.
+ >
+ }
+ />
{environmentId !== null ? (
Enter the code shown by otterdrive auth login.
+ Sign in with your Otter Account to review code ${userCode}. +
+ `; + const callbackURL = `${env.APP_URL}/device?${new URLSearchParams({ user_code: userCode })}`; + script = `document.querySelector('#sign-in').onclick = async () => { + try { + const response = await fetch('/api/auth/sign-in/social', { method: 'POST', headers: {'content-type': 'application/json'}, body: JSON.stringify({provider: 'otter', callbackURL: ${JSON.stringify(callbackURL)}, disableRedirect: true}) }); + const result = await response.json(); + if (!response.ok || !result.url) throw new Error(); + location.assign(result.url); + } catch { document.querySelector('#result').textContent = 'Could not sign in. Please try again.'; } + };`; + } else { + const device = await auth.api + .deviceVerify({ + headers: request.headers, + query: { user_code: userCode }, + }) + .catch(() => null); + if (!device || !["otterdrive-cli", "otterware-cli"].includes(device.client_id ?? "")) { + status = 400; + content = html`
+ This code is invalid or expired. Run otterdrive auth login again.
+
This connection has already been reviewed. Return to your terminal.
`; + } else { + content = html`+ Connect the CLI displaying ${userCode} to + ${session.user.email}. +
+Approve only if you started this sign-in on your own machine.
+ `; + script = `document.querySelector('#review').onsubmit = async event => { + event.preventDefault(); + try { + const action = event.submitter.value; + const response = await fetch('/api/auth/device/' + action, { method: 'POST', headers: {'content-type': 'application/json'}, body: JSON.stringify({userCode: ${JSON.stringify(userCode)}}) }); + if (!response.ok) throw new Error(); + document.querySelector('#result').textContent = action === 'approve' ? 'Approved. Return to your terminal.' : 'Connection denied.'; + document.querySelector('#review').remove(); + } catch { document.querySelector('#result').textContent = 'Could not review this connection. Please try again.'; } + };`; + } + } + } + const nonce = crypto.randomUUID(); + const body = await html` + + + + +