large entity recreation
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// dnsrecon-reduced/static/js/graph.js
|
||||
/**
|
||||
* Graph visualization module for DNSRecon
|
||||
* Handles network graph rendering using vis.js with proper large entity node hiding
|
||||
@@ -362,77 +363,60 @@ class GraphManager {
|
||||
}
|
||||
|
||||
try {
|
||||
// Initialize if not already done
|
||||
if (!this.isInitialized) {
|
||||
this.initialize();
|
||||
}
|
||||
|
||||
this.initialTargetIds = new Set(graphData.initial_targets || []);
|
||||
// Check if we have actual data to display
|
||||
const hasData = graphData.nodes.length > 0 || graphData.edges.length > 0;
|
||||
|
||||
// Handle placeholder visibility
|
||||
const placeholder = this.container.querySelector('.graph-placeholder');
|
||||
if (placeholder) {
|
||||
if (hasData) {
|
||||
placeholder.style.display = 'none';
|
||||
} else {
|
||||
placeholder.style.display = 'flex';
|
||||
// Early return if no data to process
|
||||
return;
|
||||
}
|
||||
placeholder.style.display = hasData ? 'none' : 'flex';
|
||||
}
|
||||
if (!hasData) {
|
||||
this.nodes.clear();
|
||||
this.edges.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// Process nodes with proper certificate coloring
|
||||
const processedNodes = filteredNodes.map(node => {
|
||||
const nodeMap = new Map(graphData.nodes.map(node => [node.id, node]));
|
||||
|
||||
// Filter out hidden nodes before processing for rendering
|
||||
const filteredNodes = graphData.nodes.filter(node =>
|
||||
!(node.metadata && node.metadata.large_entity_id)
|
||||
);
|
||||
|
||||
const processedNodes = graphData.nodes.map(node => {
|
||||
const processed = this.processNode(node);
|
||||
|
||||
// Apply certificate-based coloring here in frontend
|
||||
if (node.type === 'domain' && Array.isArray(node.attributes)) {
|
||||
const certInfo = this.analyzeCertificateInfo(node.attributes);
|
||||
|
||||
if (certInfo.hasExpiredOnly) {
|
||||
// Red for domains with only expired/invalid certificates
|
||||
processed.color = { background: '#ff6b6b', border: '#cc5555' };
|
||||
} else if (!certInfo.hasCertificates) {
|
||||
// Grey for domains with no certificates
|
||||
processed.color = { background: '#c7c7c7', border: '#999999' };
|
||||
}
|
||||
// Valid certificates use default green (handled by processNode)
|
||||
}
|
||||
|
||||
return processed;
|
||||
});
|
||||
|
||||
const mergedEdges = {};
|
||||
graphData.edges.forEach(edge => {
|
||||
const mergeKey = `${fromNode}-${toNode}-${edge.label}`;
|
||||
|
||||
if (!mergedEdges[mergeKey]) {
|
||||
mergedEdges[mergeKey] = {
|
||||
...edge,
|
||||
from: fromNode,
|
||||
to: toNode,
|
||||
count: 0,
|
||||
confidence_score: 0
|
||||
};
|
||||
}
|
||||
|
||||
mergedEdges[mergeKey].count++;
|
||||
if (edge.confidence_score > mergedEdges[mergeKey].confidence_score) {
|
||||
mergedEdges[mergeKey].confidence_score = edge.confidence_score;
|
||||
}
|
||||
});
|
||||
|
||||
const processedEdges = Object.values(mergedEdges).map(edge => {
|
||||
const processed = this.processEdge(edge);
|
||||
if (edge.count > 1) {
|
||||
processed.label = `${edge.label} (${edge.count})`;
|
||||
if (node.metadata && node.metadata.large_entity_id) {
|
||||
processed.hidden = true;
|
||||
}
|
||||
return processed;
|
||||
});
|
||||
|
||||
const processedEdges = graphData.edges.map(edge => {
|
||||
let fromNode = nodeMap.get(edge.from);
|
||||
let toNode = nodeMap.get(edge.to);
|
||||
let fromId = edge.from;
|
||||
let toId = edge.to;
|
||||
|
||||
if (fromNode && fromNode.metadata && fromNode.metadata.large_entity_id) {
|
||||
fromId = fromNode.metadata.large_entity_id;
|
||||
}
|
||||
if (toNode && toNode.metadata && toNode.metadata.large_entity_id) {
|
||||
toId = toNode.metadata.large_entity_id;
|
||||
}
|
||||
|
||||
// Avoid self-referencing edges from re-routing
|
||||
if (fromId === toId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const reRoutedEdge = { ...edge, from: fromId, to: toId };
|
||||
return this.processEdge(reRoutedEdge);
|
||||
}).filter(Boolean); // Remove nulls from self-referencing edges
|
||||
|
||||
// Update datasets with animation
|
||||
const existingNodeIds = this.nodes.getIds();
|
||||
const existingEdgeIds = this.edges.getIds();
|
||||
|
||||
@@ -449,11 +433,9 @@ class GraphManager {
|
||||
setTimeout(() => this.highlightNewElements(newNodes, newEdges), 100);
|
||||
}
|
||||
|
||||
if (processedNodes.length <= 10 || existingNodeIds.length === 0) {
|
||||
if (this.nodes.length <= 10 || existingNodeIds.length === 0) {
|
||||
setTimeout(() => this.fitView(), 800);
|
||||
}
|
||||
|
||||
console.log(`Graph updated: ${processedNodes.length} nodes, ${processedEdges.length} edges (${newNodes.length} new nodes, ${newEdges.length} new edges)`);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Failed to update graph:', error);
|
||||
@@ -582,7 +564,7 @@ class GraphManager {
|
||||
processEdge(edge) {
|
||||
const confidence = edge.confidence_score || 0;
|
||||
const processedEdge = {
|
||||
id: `${edge.from}-${edge.to}`,
|
||||
id: `${edge.from}-${edge.to}-${edge.label}`,
|
||||
from: edge.from,
|
||||
to: edge.to,
|
||||
label: this.formatEdgeLabel(edge.label, confidence),
|
||||
|
||||
Reference in New Issue
Block a user