clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

read the Connect page with the browser session instead of prompting the signer

Dami committed 0ace0e4
commit
0ace0e42789227359ff22b970516432fed6d70c1
parent
c656e4458f032c5baeeed9bdd279bd2ee726ce43
author
Dami <dami.etoile@gmail.com>
7 files changed, +124 -19
Mdocs/fixi.md2+-
Minternal/daemon/http.go23++++++++++++
Minternal/daemon/session_test.go25+++++++++++++
Minternal/webui/components.js17++++++++-
Minternal/webui/manage.html4+-
Minternal/webui/private-services.js59+++++++++++++++++++++++-------
Minternal/webui/webui.go13++++++-
M docs/fixi.md +1 -1
@@ -12,7 +12,7 @@ b70458c212d0409f8a6319c286351865d92587292ad4f9bc0dfd1c46ffcad855
1212 1313 The signer bridge handles NIP-07, NIP-46, Nostr Connect, Amber links, session login and management actions. Encrypted uploads, NIP-34 publishing and NIP-17 file messages sign through the same bridge and never retry a signed request on their own. Fixi updates page links and GET forms within the current tenant without a full reload. Filters, repository refs, browser history and page titles remain available. Downloads, external links and modified clicks retain normal browser behavior. A failed request displays an error in the footer and leaves the current page usable. Navigation and content also work without JavaScript, including on phones.1414 15-Signed actions require JavaScript and submit once while their controls are disabled. Connect previews update in place. Job status uses an authenticated stream that sends updates when the results change.15+Signed-in browsers read the connection list and the query bridge with their session, so opening a page never asks the signer; signatures are requested only when publishing or decrypting. Signed actions require JavaScript and submit once while their controls are disabled. Connect previews update in place. Job status uses an authenticated stream that sends updates when the results change.1616 1717 On phones, navigation starts closed and opens from the menu control, with or without JavaScript. Opening the menu leaves content in place. Desktop pages retain the sidebar.1818
M internal/daemon/http.go +23 -0
M internal/daemon/session_test.go +25 -0
M internal/webui/components.js +16 -1
M internal/webui/manage.html +2 -2
M internal/webui/private-services.js +45 -14
@@ -9,17 +9,33 @@
99 const relay = value => relayURL(value, {strict: true});1010 const mergeRows = (rows, urls) =>1111 rows.filter(row => !(Array.isArray(row) && row[0] === "g")).concat(urls.map(value => ["g", value]));12- const publicKey = async () => {12+ const publicKey = async element => {13+ const known = element?.getAttribute("pubkey");14+ if (/^[0-9a-f]{64}$/.test(known || "")) return known;1315 const active = signer();1416 if (active?.getPublicKey) return active.getPublicKey();1517 if (window.tiny?.getPublicKey) return window.tiny.getPublicKey();1618 throw Error("Connect a signer first.");1719 };20+ // readList uses the browser session when the page has one, so showing21+ // the list never asks the signer; a signed query is the fallback.1822 const readList = async pubkey => {1923 const body = JSON.stringify([{kinds: [10318], authors: [pubkey], limit: 1}]);20- const response = await window.tiny.signedFetch("/query", "POST", body, {21- contentType: "application/json"22- });24+ let response = null;25+ if (typeof fetch === "function" && window.tiny?.localPath) {26+ response = await fetch(window.tiny.localPath("/query"), {27+ method: "POST",28+ credentials: "same-origin",29+ headers: {"content-type": "application/json"},30+ body31+ });32+ if (response.status === 401) response = null;33+ }34+ if (!response) {35+ response = await window.tiny.signedFetch("/query", "POST", body, {36+ contentType: "application/json"37+ });38+ }2339 if (!response || response.ok === false) throw Error("Could not read the private relay list.");2440 const rows = await response.json();2541 if (!Array.isArray(rows) || rows.length > 1) throw Error("The private relay list response is malformed.");
@@ -83,13 +99,14 @@
8399 this.form.querySelector("button").disabled = false;84100 });85101 });86- this.whenSigned(() =>87- this.load()88- .then(() => {89- this.form.querySelector("button").disabled = false;90- })91- .catch(error => this.say("Error: " + error.message, true))92- );102+ this.querySelector("[data-decrypt]")?.addEventListener("click", () => {103+ this.whenSigned(() => this.reveal().catch(error => this.say("Error: " + error.message, true)));104+ });105+ this.load()106+ .then(() => {107+ this.form.querySelector("button").disabled = false;108+ })109+ .catch(error => this.say("Error: " + error.message, true));93110 }94111 95112 // whenSigned runs once a signer is available. The bridge announces a
@@ -106,10 +123,24 @@
106123 else delete this.output.dataset.error;107124 }108125 126+ // load reads the published event without decrypting it. Decryption127+ // asks the signer, so it waits for the Decrypt to edit control.109128 async load() {110129 this.say("Reading encrypted list…");111- const pubkey = await publicKey();112- const event = await readList(pubkey);130+ const pubkey = await publicKey(this);131+ this.event = await readList(pubkey);132+ if (!this.event) {133+ this.say("No private relay list published yet.");134+ return;135+ }136+ const control = this.querySelector("[data-decrypt]");137+ if (control) control.hidden = false;138+ this.say("An encrypted list is published. Decrypt to edit it, or publish new URLs to merge them.");139+ }140+141+ async reveal() {142+ const pubkey = await publicKey(this);143+ const event = this.event || (await readList(pubkey));113144 if (!event) {114145 this.say("No private relay list published yet.");115146 return;
@@ -132,7 +163,7 @@
132163 throw Error("Use ws:// or wss:// URLs without credentials, queries or fragments.");133164 const urls = rawURLs.map(relay);134165 const unique = [...new Set(urls)];135- const pubkey = await publicKey();166+ const pubkey = await publicKey(this);136167 const existing = await readList(pubkey);137168 let rows = [];138169 if (existing) {
M internal/webui/webui.go +12 -1