优化安全策略
This commit is contained in:
@@ -427,6 +427,7 @@
|
|||||||
<div class="modal-tabs">
|
<div class="modal-tabs">
|
||||||
<button class="modal-tab active" data-tab="prom">数据源管理</button>
|
<button class="modal-tab active" data-tab="prom">数据源管理</button>
|
||||||
<button class="modal-tab" data-tab="site">大屏设置</button>
|
<button class="modal-tab" data-tab="site">大屏设置</button>
|
||||||
|
<button class="modal-tab" data-tab="security">安全设置</button>
|
||||||
<button class="modal-tab" data-tab="latency">延迟线路管理</button>
|
<button class="modal-tab" data-tab="latency">延迟线路管理</button>
|
||||||
<button class="modal-tab" data-tab="auth">账号安全</button>
|
<button class="modal-tab" data-tab="auth">账号安全</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -507,15 +508,6 @@
|
|||||||
<option value="0">隐藏 (Hide)</option>
|
<option value="0">隐藏 (Hide)</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group" style="margin-top: 15px;">
|
|
||||||
<label for="requireLoginForServerDetailsInput">服务器详情是否仅登录后可查看</label>
|
|
||||||
<select id="requireLoginForServerDetailsInput"
|
|
||||||
style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary); width: 100%;">
|
|
||||||
<option value="1">仅登录后可查看</option>
|
|
||||||
<option value="0">允许公开查看</option>
|
|
||||||
</select>
|
|
||||||
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 6px;">开启后,未登录访客仍可看到大屏总览,但点击单台服务器时需要先登录。</p>
|
|
||||||
</div>
|
|
||||||
<div class="form-group" style="margin-top: 15px;">
|
<div class="form-group" style="margin-top: 15px;">
|
||||||
<label for="logoUrlInput">Logo URL (白天/默认,支持图片链接)</label>
|
<label for="logoUrlInput">Logo URL (白天/默认,支持图片链接)</label>
|
||||||
<input type="url" id="logoUrlInput" placeholder="https://example.com/logo_light.png">
|
<input type="url" id="logoUrlInput" placeholder="https://example.com/logo_light.png">
|
||||||
@@ -574,6 +566,26 @@
|
|||||||
</div>
|
</div>
|
||||||
<small style="display: block; margin-top: 6px; color: var(--text-muted);">选择参与 24 小时网络流量统计的 Prometheus 数据源。如果不勾选任何项,则统计所有数据源。</small>
|
<small style="display: block; margin-top: 6px; color: var(--text-muted);">选择参与 24 小时网络流量统计的 Prometheus 数据源。如果不勾选任何项,则统计所有数据源。</small>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end;">
|
||||||
|
<button class="btn btn-add" id="btnSaveSiteSettings">保存基础设置</button>
|
||||||
|
</div>
|
||||||
|
<div class="form-message" id="siteSettingsMessage"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Security Settings Tab -->
|
||||||
|
<div class="tab-content" id="tab-security">
|
||||||
|
<div class="security-settings-form">
|
||||||
|
<h3>安全与隐私设置</h3>
|
||||||
|
<div class="form-group" style="margin-top: 15px;">
|
||||||
|
<label for="requireLoginForServerDetailsInput">服务器详情是否仅登录后可查看</label>
|
||||||
|
<select id="requireLoginForServerDetailsInput"
|
||||||
|
style="padding: 10px 14px; background: var(--bg-input); border: 1px solid var(--border-color); border-radius: var(--radius-sm); color: var(--text-primary); width: 100%;">
|
||||||
|
<option value="1">仅登录后可查看</option>
|
||||||
|
<option value="0">允许公开查看</option>
|
||||||
|
</select>
|
||||||
|
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 6px;">开启后,未登录访客仍可看到大屏总览,但点击单台服务器时需要先登录。</p>
|
||||||
|
</div>
|
||||||
<div class="form-group" style="margin-top: 15px;">
|
<div class="form-group" style="margin-top: 15px;">
|
||||||
<label for="showServerIpInput">服务器详情内是否显示 IPv4 和 IPv6 地址</label>
|
<label for="showServerIpInput">服务器详情内是否显示 IPv4 和 IPv6 地址</label>
|
||||||
<select id="showServerIpInput"
|
<select id="showServerIpInput"
|
||||||
@@ -584,7 +596,7 @@
|
|||||||
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 6px;">开启后,点击服务器详情时会显示该服务器的公网 IP 地址(需 node_exporter 提供支持)。</p>
|
<p style="font-size: 0.72rem; color: var(--text-muted); margin-top: 6px;">开启后,点击服务器详情时会显示该服务器的公网 IP 地址(需 node_exporter 提供支持)。</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end;">
|
<div class="form-actions" style="margin-top: 25px; display: flex; justify-content: flex-end;">
|
||||||
<button class="btn btn-add" id="btnSaveSiteSettings">保存基础设置</button>
|
<button class="btn btn-add" id="btnSaveSecuritySettings">保存安全设置</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-message" id="siteSettingsMessage"></div>
|
<div class="form-message" id="siteSettingsMessage"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -52,6 +52,7 @@
|
|||||||
siteTitleInput: document.getElementById('siteTitleInput'),
|
siteTitleInput: document.getElementById('siteTitleInput'),
|
||||||
logoUrlInput: document.getElementById('logoUrlInput'),
|
logoUrlInput: document.getElementById('logoUrlInput'),
|
||||||
btnSaveSiteSettings: document.getElementById('btnSaveSiteSettings'),
|
btnSaveSiteSettings: document.getElementById('btnSaveSiteSettings'),
|
||||||
|
btnSaveSecuritySettings: document.getElementById('btnSaveSecuritySettings'),
|
||||||
siteSettingsMessage: document.getElementById('siteSettingsMessage'),
|
siteSettingsMessage: document.getElementById('siteSettingsMessage'),
|
||||||
logoText: document.getElementById('logoText'),
|
logoText: document.getElementById('logoText'),
|
||||||
logoIconContainer: document.getElementById('logoIconContainer'),
|
logoIconContainer: document.getElementById('logoIconContainer'),
|
||||||
@@ -541,11 +542,23 @@
|
|||||||
if (dom.logoUrlDarkInput) dom.logoUrlDarkInput.value = window.SITE_SETTINGS.logo_url_dark || '';
|
if (dom.logoUrlDarkInput) dom.logoUrlDarkInput.value = window.SITE_SETTINGS.logo_url_dark || '';
|
||||||
if (dom.faviconUrlInput) dom.faviconUrlInput.value = window.SITE_SETTINGS.favicon_url || '';
|
if (dom.faviconUrlInput) dom.faviconUrlInput.value = window.SITE_SETTINGS.favicon_url || '';
|
||||||
if (dom.showServerIpInput) dom.showServerIpInput.value = window.SITE_SETTINGS.show_server_ip ? "1" : "0";
|
if (dom.showServerIpInput) dom.showServerIpInput.value = window.SITE_SETTINGS.show_server_ip ? "1" : "0";
|
||||||
// Latency routes loaded separately in openSettings or on startup
|
|
||||||
|
// Apply security dependency
|
||||||
|
updateSecurityDependency();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadSiteSettings();
|
loadSiteSettings();
|
||||||
|
|
||||||
|
// Bind save button for security tab
|
||||||
|
if (dom.btnSaveSecuritySettings) {
|
||||||
|
dom.btnSaveSecuritySettings.addEventListener('click', saveSiteSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Security dependency listener
|
||||||
|
if (dom.requireLoginForServerDetailsInput) {
|
||||||
|
dom.requireLoginForServerDetailsInput.addEventListener('change', updateSecurityDependency);
|
||||||
|
}
|
||||||
|
|
||||||
// Track intervals for resource management
|
// Track intervals for resource management
|
||||||
initWebSocket();
|
initWebSocket();
|
||||||
backgroundIntervals.push(setInterval(fetchNetworkHistory, NETWORK_HISTORY_INTERVAL));
|
backgroundIntervals.push(setInterval(fetchNetworkHistory, NETWORK_HISTORY_INTERVAL));
|
||||||
@@ -1978,6 +1991,12 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
siteThemeQuery.addEventListener('change', siteThemeHandler);
|
siteThemeQuery.addEventListener('change', siteThemeHandler);
|
||||||
|
|
||||||
|
// Update IP visibility input
|
||||||
|
if (dom.showServerIpInput) dom.showServerIpInput.value = settings.show_server_ip ? "1" : "0";
|
||||||
|
|
||||||
|
// Sync security tab dependency
|
||||||
|
updateSecurityDependency();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Error loading site settings:', err);
|
console.error('Error loading site settings:', err);
|
||||||
}
|
}
|
||||||
@@ -2096,8 +2115,13 @@
|
|||||||
show_server_ip: dom.showServerIpInput ? (dom.showServerIpInput.value === "1") : false
|
show_server_ip: dom.showServerIpInput ? (dom.showServerIpInput.value === "1") : false
|
||||||
};
|
};
|
||||||
|
|
||||||
dom.btnSaveSiteSettings.disabled = true;
|
// UI Feedback for both potential save buttons
|
||||||
dom.btnSaveSiteSettings.textContent = '保存中...';
|
const saveButtons = [dom.btnSaveSiteSettings, dom.btnSaveSecuritySettings].filter(b => b);
|
||||||
|
saveButtons.forEach(btn => {
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.originalText = btn.textContent;
|
||||||
|
btn.textContent = '保存中...';
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/api/settings', {
|
const response = await fetch('/api/settings', {
|
||||||
@@ -2134,8 +2158,28 @@
|
|||||||
showSiteMessage(`保存失败: ${err.message}`, 'error');
|
showSiteMessage(`保存失败: ${err.message}`, 'error');
|
||||||
console.error('Save settings error:', err);
|
console.error('Save settings error:', err);
|
||||||
} finally {
|
} finally {
|
||||||
dom.btnSaveSiteSettings.disabled = false;
|
saveButtons.forEach(btn => {
|
||||||
dom.btnSaveSiteSettings.textContent = '保存设置';
|
btn.disabled = false;
|
||||||
|
btn.textContent = btn.originalText || '保存设置';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSecurityDependency() {
|
||||||
|
if (!dom.requireLoginForServerDetailsInput || !dom.showServerIpInput) return;
|
||||||
|
|
||||||
|
const requireLogin = dom.requireLoginForServerDetailsInput.value === "1";
|
||||||
|
if (!requireLogin) {
|
||||||
|
// If public access is allowed, force hide IP and disable the toggle
|
||||||
|
dom.showServerIpInput.value = "0";
|
||||||
|
dom.showServerIpInput.disabled = true;
|
||||||
|
dom.showServerIpInput.style.opacity = "0.6";
|
||||||
|
dom.showServerIpInput.parentElement.style.opacity = "0.7";
|
||||||
|
} else {
|
||||||
|
// Re-enable when login is required
|
||||||
|
dom.showServerIpInput.disabled = false;
|
||||||
|
dom.showServerIpInput.style.opacity = "1";
|
||||||
|
dom.showServerIpInput.parentElement.style.opacity = "1";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user