summaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/admin-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/admin-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/admin-page.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/admin-page.js34
1 files changed, 34 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/admin-page.js b/packages/meshbay-hub/src/meshbay_hub/static/admin-page.js
index c40d240..d5cc7a8 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/admin-page.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/admin-page.js
@@ -17,6 +17,7 @@ export function AdminPage({ token, role }) {
// and a rejected one never looks applied.
const [mailDraft, setMailDraft] = useState(null);
const [loginDraft, setLoginDraft] = useState(null);
+ const [sessionDraft, setSessionDraft] = useState(null);
const [users, setUsers] = useState([]);
const [usersTotal, setUsersTotal] = useState(0);
const [userSearch, setUserSearch] = useState('');
@@ -45,6 +46,7 @@ export function AdminPage({ token, role }) {
setSettings(data);
setMailDraft({ ...data.mail });
setLoginDraft({ ...data.login });
+ setSessionDraft({ ...data.session });
} catch (e) { setError(e.message); }
try {
setMailStatus(await hubFetch('/v1/admin/mail', { token }));
@@ -64,6 +66,7 @@ export function AdminPage({ token, role }) {
// answer rather than left showing a number that was not stored.
setMailDraft({ ...data.mail });
setLoginDraft({ ...data.login });
+ setSessionDraft({ ...data.session });
if (patch.mail) {
try {
setMailStatus(await hubFetch('/v1/admin/mail', { token }));
@@ -198,6 +201,8 @@ const MAIL_FIELDS = [
const LOGIN_FIELDS = ['max_failures', 'lockout_minutes'];
+const SESSION_FIELDS = ['browser_idle_hours', 'refresh_idle_hours', 'max_hours'];
+
// Only what changed, and only what is a number: an empty field is someone
// mid-edit, not a request to set zero.
const changedNumbers = (fields, draft, stored) => Object.fromEntries(fields
@@ -296,6 +301,35 @@ const TABS = ['general', 'stats', 'users', 'groups', 'nodes', 'logs', 'blocklist
</div>
`}
</div>
+
+ <div class="settings-section">
+ <h3 class="settings-heading">${t('admin.session_heading')}</h3>
+ <p class="settings-hint">${t('admin.session_hint')}</p>
+
+ ${sessionDraft && SESSION_FIELDS.map(key => html`
+ <div class="settings-row" key=${key}>
+ <span class="settings-label">${t('admin.session_' + key)}</span>
+ <input type="number" class="settings-number"
+ min=${(settings.session_bounds?.[key] || [0])[0]}
+ max=${(settings.session_bounds?.[key] || [0, 0])[1]}
+ value=${sessionDraft[key]}
+ disabled=${!canEditSettings || settingsSaving}
+ onInput=${e => setSessionDraft(d => ({ ...d, [key]: e.target.value }))} />
+ </div>
+ `)}
+
+ ${canEditSettings && sessionDraft && html`
+ <div class="settings-row">
+ <button class="btn" disabled=${settingsSaving}
+ onClick=${() => saveSettings({
+ session: changedNumbers(SESSION_FIELDS, sessionDraft, settings.session),
+ })}>${t('admin.session_save')}</button>
+ <button class="btn btn-secondary" disabled=${settingsSaving}
+ onClick=${() => setSessionDraft({ ...settings.session_defaults })}
+ >${t('admin.mail_reset_defaults')}</button>
+ </div>
+ `}
+ </div>
`}
`}