helwasm: colour is per name+master, not per root master
Mark correct now stores/checks the leaf's own SHA1(name||password) (correct <name>), read from the leaf warning in the enc output. Changing the name (or mistyping the master) drops back to black until that exact name+master is marked. Mark/unmark wraps add/rm for an ephemeral (not Stored) entry.
This commit is contained in:
+28
-16
@@ -68,8 +68,8 @@
|
|||||||
Type an account name and your master phrase. The password appears instantly,
|
Type an account name and your master phrase. The password appears instantly,
|
||||||
masked; click it (or the master) to reveal. Press <strong>Copy</strong>, or
|
masked; click it (or the master) to reveal. Press <strong>Copy</strong>, or
|
||||||
<strong>Store</strong> to remember the <em>name</em> (never the password).
|
<strong>Store</strong> to remember the <em>name</em> (never the password).
|
||||||
Click <strong>Mark correct</strong> once and the right master shows in colour,
|
<strong>Mark correct</strong> remembers this name and master, so that exact
|
||||||
so a typo stays black.
|
combination shows in colour; anything unmarked or mistyped stays black.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
@@ -227,6 +227,7 @@
|
|||||||
const persist = () => hel_command("save " + CATALOG_KEY);
|
const persist = () => hel_command("save " + CATALOG_KEY);
|
||||||
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
const esc = (s) => s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
||||||
const stripNoise = (out) => out.split("\n").filter((l) => l && !/^(warning|error):/.test(l));
|
const stripNoise = (out) => out.split("\n").filter((l) => l && !/^(warning|error):/.test(l));
|
||||||
|
const escapeRegExp = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||||
|
|
||||||
let toastT;
|
let toastT;
|
||||||
function toast(msg) {
|
function toast(msg) {
|
||||||
@@ -271,8 +272,8 @@
|
|||||||
b.classList.toggle("is-correct", !!enabled && !!isCorrect);
|
b.classList.toggle("is-correct", !!enabled && !!isCorrect);
|
||||||
b.textContent = enabled && isCorrect ? "Correct ✓" : "Mark correct";
|
b.textContent = enabled && isCorrect ? "Correct ✓" : "Mark correct";
|
||||||
b.title = enabled && isCorrect
|
b.title = enabled && isCorrect
|
||||||
? "This master is remembered as correct on this device. Click to forget it."
|
? "This name and master are remembered as correct on this device. Click to forget."
|
||||||
: "Remember this master as correct on this device, so the right master shows in colour.";
|
: "Remember this name and master as correct on this device, so this combination shows in colour.";
|
||||||
}
|
}
|
||||||
function quickGen(silent) {
|
function quickGen(silent) {
|
||||||
const spec = $("#qname").value.trim();
|
const spec = $("#qname").value.trim();
|
||||||
@@ -304,27 +305,38 @@
|
|||||||
hel_command("rm " + name);
|
hel_command("rm " + name);
|
||||||
}
|
}
|
||||||
const pw = stripNoise(out).pop() || "";
|
const pw = stripNoise(out).pop() || "";
|
||||||
// Colour = "is the master correct?" — derived from the engine so it reflects
|
// Colour = "is THIS name + master marked correct?" — read straight from the
|
||||||
// `correct /` / `unpass /` typed in the console too. `enc /` re-emits the root
|
// leaf's own correct-check in the enc output (per name+password, not per master),
|
||||||
// correctness check; needs secrets["/"], which the gen above just set.
|
// so changing the name (or mistyping the master) drops back to black until you
|
||||||
const rootChk = hel_command("enc /");
|
// mark that exact combination. `correct` typed in the console is reflected too.
|
||||||
const haveRoot = !/^error:/m.test(rootChk);
|
const warnRe = new RegExp("^warning: password " + escapeRegExp(name) + " is not marked as correct$", "m");
|
||||||
const masterOK = haveRoot && !/warning: password \/ is not marked as correct/.test(rootChk);
|
const correct = !!pw && !warnRe.test(out);
|
||||||
lastSecret = pw;
|
lastSecret = pw;
|
||||||
sec.textContent = pw;
|
sec.textContent = pw;
|
||||||
sec.classList.toggle("correct", !!pw && masterOK);
|
sec.classList.toggle("correct", correct);
|
||||||
lenEl.textContent = pw ? "len " + pw.length : "";
|
lenEl.textContent = pw ? "len " + pw.length : "";
|
||||||
refreshCorrectBtn(!!pw && haveRoot, masterOK);
|
refreshCorrectBtn(!!pw, correct);
|
||||||
if (!pw && !silent) toast("No output");
|
if (!pw && !silent) toast("No output");
|
||||||
}
|
}
|
||||||
function toggleCorrect() {
|
function toggleCorrect() {
|
||||||
const b = $("#markCorrect");
|
const b = $("#markCorrect");
|
||||||
if (!b || b.disabled) return;
|
if (!b || b.disabled) return;
|
||||||
const wasCorrect = b.classList.contains("is-correct");
|
const spec = $("#qname").value.trim();
|
||||||
// Store / remove the root-master hash on the device (same as the console).
|
const name = hel_parse_name(spec);
|
||||||
hel_command(wasCorrect ? "uncorrect /" : "correct /");
|
if (!name) return;
|
||||||
|
const verb = b.classList.contains("is-correct") ? "uncorrect " : "correct ";
|
||||||
|
// Mark / unmark THIS name + master on the device (stores SHA1(name‖password)).
|
||||||
|
// The entry may be ephemeral (not Stored), so wrap add/rm around it so
|
||||||
|
// correct/uncorrect can recompute the password to hash — same as the console.
|
||||||
|
if (/^error: name .* not found/m.test(hel_command("enc " + name))) {
|
||||||
|
hel_command("add " + spec);
|
||||||
|
hel_command(verb + name);
|
||||||
|
hel_command("rm " + name);
|
||||||
|
} else {
|
||||||
|
hel_command(verb + name);
|
||||||
|
}
|
||||||
quickGen(true);
|
quickGen(true);
|
||||||
toast(wasCorrect ? "Master no longer marked correct" : "Master marked correct");
|
toast(verb === "correct " ? "Marked correct" : "No longer marked correct");
|
||||||
}
|
}
|
||||||
function quickStore() {
|
function quickStore() {
|
||||||
const spec = $("#qname").value.trim();
|
const spec = $("#qname").value.trim();
|
||||||
|
|||||||
Reference in New Issue
Block a user