diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-09-30 17:13:40 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-09-30 17:13:40 +0200 |
| commit | b1ebcdeb9082457972c41a47e77494902335d262 (patch) | |
| tree | b19384b868197ecda88ce79765a0f60812dbc815 /packages/meshbay-hub/src/meshbay_hub/static/profile-page.js | |
| parent | 6d167392f6f8ede37e2794a68a3738f8ba03131d (diff) | |
| download | meshbay-b1ebcdeb9082457972c41a47e77494902335d262.tar.gz | |
feat: browser access, decided in the desktop application
Off for an account made there: its identities stay on the device and nothing is
left on nodes. Turned on from the Profile page behind a native confirmation;
each node is settled when its group next opens. The hub keeps a mirror a
browser reads to say why a group will not open; it grants nothing.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/profile-page.js')
| -rw-r--r-- | packages/meshbay-hub/src/meshbay_hub/static/profile-page.js | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js index cd00f03..7c36951 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js @@ -6,7 +6,7 @@ import { ask } from './ask.js'; import { Icon } from './icon.js'; import * as platform from './platform.js'; import { - hubFetch, HUB, session, setAuth, + hubFetch, HUB, session, setAuth, mirrorBrowserAccess, _storeBundleKey, _loadBundleKey, _storeRecoveryKey, } from './hub-client.js'; @@ -241,6 +241,46 @@ export function ProfilePage({ user, onLogout }) { } }, [rkInput, user]); + // ── Browser access (docs/MESHBAY_DESIGN.md §3.7) ──────────────────────── + // Decided in the desktop application, which keeps the identities: there it + // is a switch, and turning it on is confirmed by the application itself. A + // browser only reads the hub's mirror, to say why it cannot open a group. + const [baNative, setBaNative] = useState(false); + const [baOn, setBaOn] = useState(null); + const [baBusy, setBaBusy] = useState(false); + const [baMsg, setBaMsg] = useState(''); + useEffect(() => { + let gone = false; + (async () => { + const native = await platform.nativeKeys(); + if (gone) return; + setBaNative(native); + if (native) { + const on = await platform.keys.browserAccess(user.userId); + if (!gone) setBaOn(on); + return; + } + try { + const prefs = await hubFetch('/v1/users/me/preferences', { token: user.token }); + if (!gone) setBaOn((prefs || {}).browser_access !== 'off'); + } catch { /* shown as nothing */ } + })(); + return () => { gone = true; }; + }, [user]); + const baSet = useCallback(async (on) => { + setBaBusy(true); + setBaMsg(''); + try { + setBaOn(await platform.keys.setBrowserAccess(user.userId, on)); + await mirrorBrowserAccess(user.token, user.userId); + setBaMsg(t('settings.browser_access_next_open')); + } catch (err) { + setBaMsg(platform.bridgeMessage(err)); + } finally { + setBaBusy(false); + } + }, [user]); + useEffect(() => { hubFetch('/v1/users/me', { token: user.token }) .then(data => { @@ -539,6 +579,20 @@ export function ProfilePage({ user, onLogout }) { </div>`} </div> + ${baOn !== null && (baNative || baOn === false) && html` + <div class="settings-section"> + <h3 class="settings-heading">${t('settings.browser_access')}</h3> + ${baNative ? html` + <p class="settings-hint"> + ${baOn ? t('settings.browser_access_on_hint') : t('settings.browser_access_off_hint')} + </p> + <button class="btn-secondary" disabled=${baBusy} onClick=${() => baSet(!baOn)}> + ${baOn ? t('settings.browser_access_turn_off') : t('settings.browser_access_turn_on')} + </button> + ${baMsg && html`<p class="settings-hint">${baMsg}</p>`} + ` : html`<p class="settings-hint">${t('settings.browser_access_off_in_browser')}</p>`} + </div>`} + <div class="settings-section"> <h3 class="settings-heading">${t('settings.sessions_heading')}</h3> <p class="settings-hint">${t('settings.sign_out_everywhere_hint')}</p> |