Vestibule/extension/unlock.js

65 lines
1.9 KiB
JavaScript
Executable File

// Vestibule unlock popup — production implementation.
//
// Opens as a browser.windows.create popup. Sends the password to the
// background script, which forwards to usher for Argon2id verification.
// On success: the popup closes and the background clears the lock
// overlay + enters admin grace mode. On failure: shows error, clears
// input, refocuses.
const REASON_MESSAGES = {
invalid: "Invalid unlock code.",
"not-configured": "No unlock password configured. Run the admin wizard (Ctrl+Shift+V).",
};
document.getElementById("unlock-form").addEventListener("submit", (e) => {
e.preventDefault();
const password = document.getElementById("unlock-password").value;
if (!password) return;
const submitBtn = e.target.querySelector("button[type=submit]");
submitBtn.disabled = true;
submitBtn.textContent = "Verifying...";
browser.runtime
.sendMessage({ type: "unlock-attempt", password })
.then(() => {
// Result arrives asynchronously via runtime.onMessage.
// The button re-enables when the result lands.
})
.catch(() => {
resetForm("Communication error. Try again.");
});
});
browser.runtime.onMessage.addListener((msg) => {
if (msg.type !== "unlock-result") return;
if (msg.granted) {
window.close();
return;
}
const message = REASON_MESSAGES[msg.reason] || "Unlock failed.";
resetForm(message);
});
function resetForm(errorMessage) {
const input = document.getElementById("unlock-password");
const submitBtn = document.querySelector("button[type=submit]");
const errorEl = document.getElementById("unlock-error");
input.value = "";
input.focus();
submitBtn.disabled = false;
submitBtn.textContent = "Unlock";
if (errorMessage) {
errorEl.textContent = errorMessage;
errorEl.hidden = false;
} else {
errorEl.hidden = true;
}
}
console.log("[vestibule-unlock] popup loaded");