修复安全边界问题
This commit is contained in:
@@ -623,10 +623,11 @@
|
||||
}
|
||||
|
||||
function updateFavicon(url) {
|
||||
if (!url) return;
|
||||
const safeUrl = sanitizeAssetUrl(url);
|
||||
if (!safeUrl) return;
|
||||
const link = dom.siteFavicon || document.querySelector("link[rel*='icon']");
|
||||
if (link) {
|
||||
link.href = url;
|
||||
link.href = safeUrl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -675,6 +676,51 @@
|
||||
}
|
||||
}
|
||||
|
||||
function promptLogin(message = '该操作需要登录') {
|
||||
openLoginModal();
|
||||
if (message) {
|
||||
dom.loginError.textContent = message;
|
||||
dom.loginError.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeAssetUrl(url) {
|
||||
if (!url || typeof url !== 'string') return null;
|
||||
const trimmed = url.trim();
|
||||
if (!trimmed) return null;
|
||||
if (/^(https?:|data:image\/|\/)/i.test(trimmed)) return trimmed;
|
||||
return null;
|
||||
}
|
||||
|
||||
function renderLogoImage(url) {
|
||||
if (!dom.logoIconContainer) return;
|
||||
const safeUrl = sanitizeAssetUrl(url);
|
||||
|
||||
if (safeUrl) {
|
||||
const img = document.createElement('img');
|
||||
img.src = safeUrl;
|
||||
img.alt = 'Logo';
|
||||
img.className = 'logo-icon-img';
|
||||
dom.logoIconContainer.replaceChildren(img);
|
||||
return;
|
||||
}
|
||||
|
||||
dom.logoIconContainer.innerHTML = `
|
||||
<svg class="logo-icon" id="logoSvg" viewBox="0 0 32 32" fill="none">
|
||||
<rect x="2" y="2" width="28" height="28" rx="8" stroke="url(#logoGrad)" stroke-width="2.5"/>
|
||||
<path d="M8 22 L12 14 L16 18 L20 10 L24 16" stroke="url(#logoGrad)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<circle cx="12" cy="14" r="2" fill="url(#logoGrad)"/>
|
||||
<circle cx="20" cy="10" r="2" fill="url(#logoGrad)"/>
|
||||
<defs>
|
||||
<linearGradient id="logoGrad" x1="0" y1="0" x2="32" y2="32">
|
||||
<stop offset="0%" stop-color="#6366f1"/>
|
||||
<stop offset="100%" stop-color="#06b6d4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
|
||||
function openLoginModal() {
|
||||
dom.loginModal.classList.add('active');
|
||||
dom.loginError.style.display = 'none';
|
||||
@@ -1479,6 +1525,11 @@
|
||||
try {
|
||||
const url = `/api/metrics/server-details?instance=${encodeURIComponent(instance)}&job=${encodeURIComponent(job)}&source=${encodeURIComponent(source)}`;
|
||||
const response = await fetch(url);
|
||||
if (response.status === 401) {
|
||||
closeServerDetail();
|
||||
promptLogin('登录后可查看服务器详细指标');
|
||||
return;
|
||||
}
|
||||
if (!response.ok) throw new Error('Fetch failed');
|
||||
const data = await response.json();
|
||||
currentServerDetail.memTotal = data.memTotal;
|
||||
@@ -1697,6 +1748,10 @@
|
||||
}
|
||||
|
||||
const res = await fetch(url);
|
||||
if (res.status === 401) {
|
||||
promptLogin('登录后可查看历史曲线与服务器详细信息');
|
||||
return;
|
||||
}
|
||||
if (!res.ok) throw new Error('Query failed');
|
||||
const data = await res.json();
|
||||
|
||||
@@ -1883,25 +1938,7 @@
|
||||
logoToUse = settings.logo_url_dark;
|
||||
}
|
||||
|
||||
if (logoToUse) {
|
||||
dom.logoIconContainer.innerHTML = `<img src="${escapeHtml(logoToUse)}" alt="Logo" class="logo-icon-img">`;
|
||||
} else {
|
||||
// Restore default SVG
|
||||
dom.logoIconContainer.innerHTML = `
|
||||
<svg class="logo-icon" id="logoSvg" viewBox="0 0 32 32" fill="none">
|
||||
<rect x="2" y="2" width="28" height="28" rx="8" stroke="url(#logoGrad)" stroke-width="2.5"/>
|
||||
<path d="M8 22 L12 14 L16 18 L20 10 L24 16" stroke="url(#logoGrad)" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" fill="none"/>
|
||||
<circle cx="12" cy="14" r="2" fill="url(#logoGrad)"/>
|
||||
<circle cx="20" cy="10" r="2" fill="url(#logoGrad)"/>
|
||||
<defs>
|
||||
<linearGradient id="logoGrad" x1="0" y1="0" x2="32" y2="32">
|
||||
<stop offset="0%" stop-color="#6366f1"/>
|
||||
<stop offset="100%" stop-color="#06b6d4"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
`;
|
||||
}
|
||||
renderLogoImage(logoToUse || null);
|
||||
|
||||
// Favicon
|
||||
updateFavicon(settings.favicon_url);
|
||||
@@ -2021,6 +2058,10 @@
|
||||
async function loadLatencyRoutes() {
|
||||
try {
|
||||
const response = await fetch('/api/latency-routes');
|
||||
if (response.status === 401) {
|
||||
promptLogin('登录后可管理延迟线路');
|
||||
return;
|
||||
}
|
||||
const routes = await response.json();
|
||||
renderLatencyRoutes(routes);
|
||||
} catch (err) {
|
||||
@@ -2253,6 +2294,10 @@
|
||||
async function loadSources() {
|
||||
try {
|
||||
const response = await fetch('/api/sources');
|
||||
if (response.status === 401) {
|
||||
promptLogin('登录后可查看和管理数据源');
|
||||
return;
|
||||
}
|
||||
const sources = await response.json();
|
||||
const sourcesArray = Array.isArray(sources) ? sources : [];
|
||||
const promSources = sourcesArray.filter(s => s.type !== 'blackbox');
|
||||
@@ -2484,6 +2529,9 @@
|
||||
async function loadSourceCount() {
|
||||
try {
|
||||
const response = await fetch('/api/sources');
|
||||
if (response.status === 401) {
|
||||
return;
|
||||
}
|
||||
const sources = await response.json();
|
||||
const sourcesArray = Array.isArray(sources) ? sources : [];
|
||||
const promSources = sourcesArray.filter(s => s.type !== 'blackbox');
|
||||
|
||||
Reference in New Issue
Block a user