Files
hub/public/login.js
T

44 lines
3.0 KiB
JavaScript

const $ = s => document.querySelector(s);
const fail = e => { $('#err').textContent = e && e.name === 'NotAllowedError' ? 'Cancelled. Try again.' : (e.message || String(e)); };
async function signIn() {
$('#err').textContent = '';
try { await passkeyLogin(); location.replace('/'); } catch (e) { fail(e); }
}
async function init() {
if (!window.PublicKeyCredential) { $('#sub').textContent = ''; return fail(new Error('This browser does not support passkeys.')); }
const st = await (await fetch('/api/auth/state')).json();
if (st.authed) return location.replace('/');
if (st.registered) {
$('#sub').textContent = 'Sign in with your passkey';
$('#ui').innerHTML = '<button class="btn" id="go">Sign in with passkey</button>';
$('#go').onclick = signIn;
$('#ui').insertAdjacentHTML('beforeend', '<p style="margin-top:18px"><a href="#" id="inv" style="color:var(--accent)">New device or lost your devices? Use an invite or recovery code</a></p>');
$('#inv').onclick = e => {
e.preventDefault(); $('#err').textContent = ''; $('#sub').textContent = 'Add this device';
$('#ui').innerHTML = `<form id="f"><p class="sub">On a device that is already signed in, open Settings and tap <b>Invite a device</b>. Lost every device? Use one of the <b>recovery codes</b> you made in Settings.</p>
<label for="ic">Invite or recovery code</label><input type="text" id="ic" placeholder="ABCD-2345" autocomplete="off" autocapitalize="characters" required>
<label for="nm">Name this passkey</label><input type="text" id="nm" value="${/iPad|iPhone/.test(navigator.userAgent) ? 'iPhone/iPad' : 'This device'}" autocomplete="off">
<div class="bar"><button class="btn">Create passkey</button></div><p style="text-align:center"><a href="/login" style="color:var(--accent)">Back to sign in</a></p></form>`;
$('#f').onsubmit = async ev => {
ev.preventDefault(); $('#err').textContent = '';
try { await passkeyRegister('', $('#nm').value.trim() || 'Passkey', $('#ic').value.trim()); location.replace('/'); } catch (err) { fail(err); }
};
};
// Offer the passkey straight away unless the user came here to use an invite code.
signIn();
} else {
$('#sub').textContent = 'First-time setup: create a passkey for this device';
$('#ui').innerHTML = `<form id="f"><label for="sc">Setup code (from the server log or HUB_SETUP_CODE)</label>
<input type="text" id="sc" autocomplete="off" autocapitalize="off" required>
<label for="nm">Name this passkey</label><input type="text" id="nm" value="${/iPad|iPhone/.test(navigator.userAgent) ? 'iPhone/iPad' : 'This device'}" autocomplete="off">
<div class="bar"><button class="btn">Create passkey</button></div></form>`;
$('#f').onsubmit = async e => {
e.preventDefault(); $('#err').textContent = '';
try { await passkeyRegister($('#sc').value.trim(), $('#nm').value.trim() || 'Passkey'); location.replace('/'); } catch (err) { fail(err); }
};
}
}
init().catch(fail);