aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-15 02:16:39 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-15 02:21:01 +0200
commit73ad8e4eb566fe682107fa7e50ef624591199e99 (patch)
treeff0017d014d46d8835487c080dca55c6def7fd6b /packages/meshbay-hub/src/meshbay_hub/static/profile-page.js
parentbdefcd025604f2c3009fe5e0cc01213c2ba62a6a (diff)
downloadmeshbay-73ad8e4eb566fe682107fa7e50ef624591199e99.tar.gz
feat(hub): session lifetime is an admin setting, and a browser signs out when idle
Browser idle sign-out (media playback counts as activity; not the desktop app), refresh idle window and maximum session length, in hours. Sign-out now revokes on the hub, and the profile has "sign out everywhere". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XuNrwLf5EFWCMHzfoEvnpm
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.js26
1 files changed, 26 insertions, 0 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 7e355e7..4d452e1 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js
@@ -42,6 +42,23 @@ export function ProfilePage({ user, onLogout }) {
const [delPass, setDelPass] = useState('');
const [delError, setDelError] = useState('');
const [deleting, setDeleting] = useState(false);
+ const [revoking, setRevoking] = useState(false);
+ const [revokeError, setRevokeError] = useState('');
+
+ // Every session of this account stops renewing, this one included — the
+ // case it exists for is a browser left signed in somewhere else.
+ const signOutEverywhere = useCallback(async () => {
+ if (!confirm(t('settings.sign_out_everywhere_confirm'))) return;
+ setRevoking(true);
+ setRevokeError('');
+ try {
+ await hubFetch('/v1/users/me/sessions/revoke', { method: 'POST', token: user.token });
+ onLogout();
+ } catch (err) {
+ setRevokeError(err.message);
+ setRevoking(false);
+ }
+ }, [user, onLogout]);
const deleteAccount = useCallback(async (e) => {
e.preventDefault();
@@ -485,6 +502,15 @@ export function ProfilePage({ user, onLogout }) {
</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>
+ ${revokeError && html`<p class="error-msg">${revokeError}</p>`}
+ <button class="btn-secondary" disabled=${revoking} onClick=${signOutEverywhere}>
+ ${revoking ? '…' : t('settings.sign_out_everywhere')}
+ </button>
+ </div>
+
+ <div class="settings-section">
<h3 class="settings-heading">${t('settings.danger')}</h3>
<p class="settings-hint">${t('settings.delete_hint')}</p>
${delError && html`<p class="error-msg">${delError}</p>`}