diff --git a/webui/static/init.js b/webui/static/init.js index 57af415c..6d069d68 100644 --- a/webui/static/init.js +++ b/webui/static/init.js @@ -863,6 +863,11 @@ function updateProfileIndicator() { name.textContent = currentProfile.name; indicator.style.display = 'flex'; + // Service Status quick-switch is admin-only — drop the clickable affordance + // for non-admins so it doesn't look interactive. + const statusSection = document.querySelector('.status-section--clickable'); + if (statusSection) statusSection.classList.toggle('status-section--locked', !currentProfile.is_admin); + indicator.onclick = async () => { const res = await fetch('/api/profiles'); const data = await res.json(); diff --git a/webui/static/service-switch.js b/webui/static/service-switch.js index a585b681..acef7a7d 100644 --- a/webui/static/service-switch.js +++ b/webui/static/service-switch.js @@ -61,6 +61,16 @@ function _ssDownloadInfo(id) { } function openServiceSwitchModal(tab) { + // Admin-only: active metadata source / media server / download source are + // app-wide infrastructure. Non-admins manage their own playlist accounts + // elsewhere (per-profile), not here. + try { + const ctx = (typeof getCurrentProfileContext === 'function') ? getCurrentProfileContext() : null; + if (ctx && !ctx.isAdmin) { + if (typeof showToast === 'function') showToast('Only the admin can change the active sources', 'info'); + return; + } + } catch (_e) { /* if context unknown, fall through (defaults to admin) */ } _ssState.tab = _SS_TABS.some(t => t.id === tab) ? tab : 'metadata'; let overlay = document.getElementById('service-switch-overlay'); if (!overlay) { diff --git a/webui/static/style.css b/webui/static/style.css index d6c56f7e..760e886a 100644 --- a/webui/static/style.css +++ b/webui/static/style.css @@ -67764,3 +67764,7 @@ body.em-scroll-lock { overflow: hidden; } } .ss-hybrid-logo { width: 26px; height: 26px; object-fit: contain; } .ss-hybrid-name { font-size: 0.9rem; } + +/* Service Status is admin-only — non-admins get no clickable affordance. */ +.status-section--locked { cursor: default; } +.status-section--locked:hover { background: transparent; }