mirror of
https://github.com/Ed1s0nZ/CyberStrikeAI.git
synced 2026-08-02 00:48:55 +02:00
Add files via upload
This commit is contained in:
+32
-4
@@ -1630,8 +1630,36 @@ function importFofaRowAsset(index) {
|
||||
return importFofaAssetsByIndexes([Number(index)]);
|
||||
}
|
||||
|
||||
function assetDetailItem(label, value, wide) {
|
||||
return `<div class="asset-detail-item${wide ? ' asset-detail-item--wide' : ''}"><span>${escapeHtml(label)}</span><div>${value || '<span class="muted">-</span>'}</div></div>`;
|
||||
function assetDetailItem(label, value, wide, options) {
|
||||
const itemClass = ['asset-detail-item'];
|
||||
if (wide) itemClass.push('asset-detail-item--wide');
|
||||
if (options?.className) itemClass.push(options.className);
|
||||
return `<div class="${itemClass.join(' ')}"><span>${escapeHtml(label)}</span><div>${value || '<span class="muted">-</span>'}</div></div>`;
|
||||
}
|
||||
|
||||
function assetDetailBadge(label, value, modifier) {
|
||||
if (!value) return '';
|
||||
const badgeClass = modifier ? ` asset-detail-overview-badge--${modifier}` : '';
|
||||
return `<span class="asset-detail-overview-badge${badgeClass}"><span>${escapeHtml(label)}</span>${escapeHtml(value)}</span>`;
|
||||
}
|
||||
|
||||
function assetDetailOverview(asset) {
|
||||
const service = [asset.protocol, asset.port ? ':' + asset.port : ''].join('');
|
||||
const location = [asset.country, asset.province, asset.city].filter(Boolean).join(' / ');
|
||||
const statusLabel = asset.status === 'inactive' ? assetT('assets.statusInactive', '停用') : assetT('assets.statusActive', '活跃');
|
||||
const risk = assetRiskPresentation(asset.risk_level);
|
||||
return `<section class="asset-detail-overview">
|
||||
<div class="asset-detail-overview-main">
|
||||
<div class="asset-detail-target">${escapeHtml(assetTargetLabel(asset))}</div>
|
||||
<div class="asset-detail-meta-line">${escapeHtml([asset.ip, asset.domain, service].filter(Boolean).join(' · ') || '-')}</div>
|
||||
</div>
|
||||
<div class="asset-detail-overview-badges">
|
||||
${assetDetailBadge(assetT('assets.status', '状态'), statusLabel, asset.status === 'inactive' ? 'neutral' : 'success')}
|
||||
${assetDetailBadge(assetT('assets.risk', '风险'), risk.label, risk.level)}
|
||||
${assetDetailBadge(assetT('assets.source', '来源'), asset.source || '', 'source')}
|
||||
${assetDetailBadge(assetT('assets.location', '地区'), location, 'location')}
|
||||
</div>
|
||||
</section>`;
|
||||
}
|
||||
|
||||
function openAssetDetail(index) {
|
||||
@@ -1662,7 +1690,7 @@ function openAssetDetailRecord(asset) {
|
||||
assetDetailItem(assetT('assets.environment', '环境'), escapeHtml(asset.environment || '')),
|
||||
assetDetailItem(assetT('assets.criticality', '重要性'), escapeHtml(asset.criticality || '')),
|
||||
assetDetailItem(assetT('assets.source', '来源'), escapeHtml(asset.source || '')),
|
||||
assetDetailItem(assetT('assets.sourceQuery', '来源查询'), asset.source_query ? `<code>${escapeHtml(asset.source_query)}</code>` : ''),
|
||||
assetDetailItem(assetT('assets.sourceQuery', '来源查询'), asset.source_query ? `<code>${escapeHtml(asset.source_query)}</code>` : '', true, { className: 'asset-detail-item--code' }),
|
||||
assetDetailItem(assetT('assets.tagsLabel', '标签'), tags, true),
|
||||
assetDetailItem(assetT('assets.firstSeen', '首次发现'), escapeHtml(asset.first_seen_at ? new Date(asset.first_seen_at).toLocaleString() : '')),
|
||||
assetDetailItem(assetT('assets.lastSeen', '最近发现'), escapeHtml(asset.last_seen_at ? new Date(asset.last_seen_at).toLocaleString() : '')),
|
||||
@@ -1670,7 +1698,7 @@ function openAssetDetailRecord(asset) {
|
||||
assetDetailItem(assetT('assets.relatedVulnerabilities', '相关漏洞'), String(Number(asset.vulnerability_count || 0)))
|
||||
];
|
||||
const grid = document.getElementById('asset-detail-grid');
|
||||
if (grid) grid.innerHTML = values.join('');
|
||||
if (grid) grid.innerHTML = assetDetailOverview(asset) + `<div class="asset-detail-fields">${values.join('')}</div>`;
|
||||
if (typeof applyRBACToUI === 'function') applyRBACToUI(document.getElementById('asset-detail-modal'));
|
||||
if (typeof openAppModal === 'function') openAppModal('asset-detail-modal');
|
||||
else document.getElementById('asset-detail-modal').style.display = 'flex';
|
||||
|
||||
@@ -1096,7 +1096,7 @@ async function loadProjectAssets(page) {
|
||||
<td>${escapeHtml(asset.source || '-')}</td>
|
||||
<td>${escapeHtml(updated)}</td>
|
||||
<td><span class="asset-status asset-status--${escapeHtml(asset.status || 'active')}">${escapeHtml(status)}</span></td>
|
||||
<td class="col-actions"><div class="projects-table-actions"><button type="button" class="projects-action-btn projects-action-btn--view" onclick="openProjectAssetDetail(${index})">${escapeHtml(tpFmt('common.view', '查看'))}</button></div></td>
|
||||
<td class="col-actions"><div class="projects-table-actions"><button type="button" class="projects-action-btn projects-action-btn--mute" data-require-permission="asset:write" onclick="unbindAssetFromProject(${index})" title="${escapeHtml(tp('projects.unbindProjectTitle'))}">${escapeHtml(tp('projects.unbind'))}</button></div></td>
|
||||
</tr>`;
|
||||
}).join('');
|
||||
renderProjectAssetsPagination();
|
||||
@@ -1147,6 +1147,29 @@ function openProjectAssetDetail(index) {
|
||||
if (asset && typeof window.openAssetDetailRecord === 'function') window.openAssetDetailRecord(asset);
|
||||
}
|
||||
|
||||
async function unbindAssetFromProject(index) {
|
||||
const asset = currentProjectAssets[Number(index)];
|
||||
if (!asset || !asset.id || !currentProjectId) return;
|
||||
const target = asset.host || asset.domain || asset.ip || asset.id;
|
||||
const message = tpFmt('projects.unbindAssetConfirm', `确定将“${target}”从当前项目解绑吗?资产不会被删除。`, { target });
|
||||
if (!confirm(message)) return;
|
||||
try {
|
||||
const res = await apiFetch('/api/assets/project-binding', {
|
||||
method: 'PUT',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ asset_ids: [asset.id], project_id: '' })
|
||||
});
|
||||
if (!res.ok) throw new Error(await res.text());
|
||||
if (typeof showInlineToast === 'function') {
|
||||
showInlineToast(tpFmt('projects.unbindAssetDone', '已从项目解绑资产', { target }));
|
||||
}
|
||||
await loadProjectAssets(projectAssetsPagination.page);
|
||||
await refreshProjectHeaderStats();
|
||||
} catch (error) {
|
||||
alert(`${tp('projects.unbindFailed')}: ${error.message || error}`);
|
||||
}
|
||||
}
|
||||
|
||||
let _selectedGraphFactKey = null;
|
||||
let _selectedGraphEdgeId = null;
|
||||
let _currentGraphData = null;
|
||||
@@ -2879,6 +2902,7 @@ window.unbindConversationFromProject = unbindConversationFromProject;
|
||||
window.loadProjectConversations = loadProjectConversations;
|
||||
window.loadProjectAssets = loadProjectAssets;
|
||||
window.openProjectAssetDetail = openProjectAssetDetail;
|
||||
window.unbindAssetFromProject = unbindAssetFromProject;
|
||||
window.loadProjectFactGraph = loadProjectFactGraph;
|
||||
window.filterProjectFactGraph = filterProjectFactGraph;
|
||||
window.centerProjectFactGraph = centerProjectFactGraph;
|
||||
|
||||
Reference in New Issue
Block a user