diigo-cache: webkey page logs in with the password manager
/cache/ without a fragment is now a login form: petname (autocomplete=username) and cache id (type=password, autocomplete=current-password), the shape password managers fill from the entries the save button makes. Its inputs have no name, so a native submit (script failed) sends nothing; the key stays in memory, out of the address bar and history. Home links to it. Generated-by: Claude Opus 5.5
This commit is contained in:
1 parent
961515d8db
commit
efaf74023d
3 files changed
+37
-2
No files matched your search
@@ -5,6 +5,11 @@
|
||||
* it for a capability (`api.cache(key)`, Cap'n Web over /api, in-band),
|
||||
* and drives the fill job. Each round trip is its own HTTP batch session:
|
||||
* calls made before an await travel together.
|
||||
*
|
||||
* Without a fragment, the page is a login form a password manager fills
|
||||
* (petname as username, cache id as password). Its inputs have no
|
||||
* `name`, so a native submit (script failed) sends nothing; the key
|
||||
* stays in memory, out of the address bar and history.
|
||||
*/
|
||||
|
||||
export const CACHE_PAGE_HTML = `<!doctype html>
|
||||
@@ -13,6 +18,11 @@ export const CACHE_PAGE_HTML = `<!doctype html>
|
||||
<body>
|
||||
<h1>diigo cache <code id="fingerprint"></code></h1>
|
||||
<p id="problem" hidden></p>
|
||||
<form id="login" hidden>
|
||||
<p><label>petname <input id="login-petname" autocomplete="username" size="24"></label></p>
|
||||
<p><label>cache id <input id="login-key" type="password" autocomplete="current-password" size="24" required></label></p>
|
||||
<p><button type="submit">open</button></p>
|
||||
</form>
|
||||
<section id="private" hidden>
|
||||
<h2>private cache</h2>
|
||||
<p id="private-status">no fill job yet</p>
|
||||
@@ -29,7 +39,7 @@ export const CACHE_PAGE_HTML = `<!doctype html>
|
||||
<script type="module">
|
||||
import { newHttpBatchRpcSession } from "/_capnweb.js";
|
||||
|
||||
const key = location.hash.slice(1);
|
||||
let key = location.hash.slice(1);
|
||||
const $ = (id) => document.getElementById(id);
|
||||
const problem = (text) => {
|
||||
$("problem").textContent = text;
|
||||
@@ -71,8 +81,21 @@ function report(err) {
|
||||
problem(String(err));
|
||||
}
|
||||
|
||||
/** no fragment: ask for the key (the password manager fills it in) */
|
||||
function login() {
|
||||
const form = $("login");
|
||||
form.hidden = false;
|
||||
form.addEventListener("submit", (event) => {
|
||||
event.preventDefault();
|
||||
key = $("login-key").value.trim();
|
||||
if (!key) return;
|
||||
form.hidden = true;
|
||||
main().catch(report);
|
||||
});
|
||||
}
|
||||
|
||||
async function main() {
|
||||
if (!key) return problem("no key: this page's address should end in #<cache id>");
|
||||
if (!key) return login();
|
||||
const c = cap();
|
||||
const [fingerprint, hasPublic] = await Promise.all([c.fingerprint(), c.hasPublic()]);
|
||||
$("fingerprint").textContent = fingerprint;
|
||||
|
||||
@@ -582,6 +582,7 @@ nobody here opens it. Mint lands you on the wire step, id pre-filled.</li>
|
||||
<p><button type="submit">wire</button></p>
|
||||
</form>
|
||||
<p>the ids this mints are for <b>you</b>: copy them somewhere you control (password manager)</p>
|
||||
<p><a href="/cache/">open a cache</a> — fill it, watch progress (your password manager can fill in the cache id)</p>
|
||||
${dumpForm}
|
||||
${result}
|
||||
</body></html>`,
|
||||
|
||||
Reference in new issue
Block a user