Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,863 changes: 1,300 additions & 563 deletions scripts/demo_data.py

Large diffs are not rendered by default.

155 changes: 110 additions & 45 deletions templates/cases/detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,20 +150,6 @@ <h6 class="mb-0"><i class="bi bi-chat-left-text me-2"></i>Comments</h6>
<div class="row g-2" id="imagesGrid"></div>
</div>

<!-- Image Upload Widget -->
<div class="mb-3">
<div class="input-group">
<input type="file" class="form-control" id="imageInput" accept="image/*" multiple>
<button class="btn btn-outline-secondary" type="button" id="uploadImageBtn">
<i class="bi bi-image me-1"></i> Add Images
</button>
</div>
<small class="text-muted d-block mt-1">
<i class="bi bi-info-circle me-1"></i>
PNG, JPG, GIF, WebP, BMP up to 10MB each
</small>
</div>

<form id="commentForm">
<div class="mb-2">
<textarea class="form-control" id="newComment" rows="3" placeholder="Add a comment..."></textarea>
Expand Down Expand Up @@ -244,25 +230,12 @@ <h6 class="mb-0"><i class="bi bi-exclamation-triangle me-2"></i>Linked Incidents
<span class="text-muted">Loading...</span>
</div>
</div>
</div>

<!-- Relationships Graph Link -->
<div class="card">
<div class="card-header">
<h6 class="mb-0"><i class="bi bi-diagram-3 me-2"></i>Relationships</h6>
</div>
<div class="card-body">
<p class="text-muted small mb-3">View all relationships and connections for this case</p>
<a href="#caseGraphContainer" class="btn btn-primary w-100 btn-sm" onclick="scrollToGraph()">
<i class="bi bi-eye me-1"></i> View Graph
</a>
</div>
</div>
</div><
</div>
</div>

<!-- Graph Visualization -->
<div class="card mb-4">
<div class="card mb-4 mt-4">
<div class="card-header bg-white d-flex justify-content-between align-items-center">
<h6 class="mb-0">
<i class="bi bi-diagram-3 me-2"></i> Relationships Graph
Expand Down Expand Up @@ -1292,6 +1265,11 @@ <h6 class="mb-1"><strong>${escapeHtml(inc.title)}</strong></h6>
style: {
'content': 'data(label)',
'background-color': 'data(color)',
'background-image': 'data(icon)',
'background-fit': 'none',
'background-width': '55%',
'background-height': '55%',
'background-clip': 'none',
'width': 40,
'height': 40,
'border-width': 2,
Expand All @@ -1300,8 +1278,9 @@ <h6 class="mb-1"><strong>${escapeHtml(inc.title)}</strong></h6>
'color': 'white',
'text-outline-width': 1,
'text-outline-color': '#333',
'text-valign': 'center',
'text-valign': 'bottom',
'text-halign': 'center',
'text-margin-y': 5,
'padding': 3
}
},
Expand All @@ -1317,8 +1296,9 @@ <h6 class="mb-1"><strong>${escapeHtml(inc.title)}</strong></h6>
{
selector: 'node.case',
style: {
'shape': 'square',
'shape': 'round-rectangle',
'background-color': '#0d6efd',
'background-image': 'data(icon)',
'border-color': '#0b5ed7',
'width': 45,
'height': 45
Expand All @@ -1329,17 +1309,19 @@ <h6 class="mb-1"><strong>${escapeHtml(inc.title)}</strong></h6>
style: {
'shape': 'diamond',
'background-color': '#dc3545',
'background-image': 'data(icon)',
'border-color': '#bb2d3b',
'width': 45,
'height': 45
'width': 50,
'height': 50
}
},
{
selector: 'node[entity_type="stix"]',
style: {
'shape': 'ellipse',
'background-color': '#17a2b8',
'border-color': '#138496',
'background-color': 'data(color)',
'background-image': 'data(icon)',
'border-color': '#333',
'width': 40,
'height': 40
}
Expand Down Expand Up @@ -1448,6 +1430,84 @@ <h6 class="mb-1"><strong>${escapeHtml(inc.title)}</strong></h6>

if (!container) return;

// STIX type icon mapping (Bootstrap Icons)
const typeIcons = {
'indicator': 'crosshair',
'malware': 'bug-fill',
'threat-actor': 'person-fill-exclamation',
'attack-pattern': 'bullseye',
'campaign': 'megaphone-fill',
'tool': 'tools',
'vulnerability': 'shield-exclamation',
'infrastructure': 'hdd-network-fill',
'intrusion-set': 'diagram-3-fill',
'identity': 'person-badge-fill',
'location': 'geo-alt-fill',
'course-of-action': 'shield-check',
'note': 'sticky-fill',
'opinion': 'chat-square-text-fill',
'report': 'file-earmark-text-fill',
'observed-data': 'eye-fill',
'case': 'folder-fill',
'incident': 'exclamation-triangle-fill',
'stix': 'crosshair',
'ioc': 'crosshair'
};

// SVG icon paths for Bootstrap Icons
const iconPaths = {
'crosshair': '<path d="M8.5.5a.5.5 0 0 0-1 0v.518A7.001 7.001 0 0 0 1.018 7.5H.5a.5.5 0 0 0 0 1h.518a7.001 7.001 0 0 0 6.482 6.482v.518a.5.5 0 0 0 1 0v-.518A7.001 7.001 0 0 0 14.982 8.5h.518a.5.5 0 0 0 0-1h-.518A7.001 7.001 0 0 0 8.5 1.018V.5Zm-6.48 7A6.001 6.001 0 0 1 7.5 2.02v.48a.5.5 0 0 0 1 0v-.48a6.001 6.001 0 0 1 5.48 5.48h-.48a.5.5 0 0 0 0 1h.48a6.002 6.002 0 0 1-5.48 5.48v-.48a.5.5 0 0 0-1 0v.48A6.001 6.001 0 0 1 2.02 8.5h.48a.5.5 0 0 0 0-1h-.48ZM8 10a2 2 0 1 0 0-4 2 2 0 0 0 0 4Z"/>',
'bug-fill': '<path d="M4.978.855a.5.5 0 1 0-.956.29l.41 1.352A4.985 4.985 0 0 0 3 6h10a4.985 4.985 0 0 0-1.432-3.503l.41-1.352a.5.5 0 1 0-.956-.29l-.291.956A4.978 4.978 0 0 0 8 1a4.979 4.979 0 0 0-2.731.811l-.29-.956z"/><path d="M13 6v1H8.5V8H14a1 1 0 0 1 1 1v.5h-2a.5.5 0 0 0 0 1h2v1h-2a.5.5 0 0 0 0 1h2v1h-2a.5.5 0 0 0 0 1h2A1 1 0 0 1 14 15h-.5a.5.5 0 0 0 0 1H14a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-1V6h.5a.5.5 0 0 0 0-1H13v1zM3 6v1h4.5V8H2a1 1 0 0 0-1 1v.5h2a.5.5 0 0 1 0 1H1v1h2a.5.5 0 0 1 0 1H1v1h2a.5.5 0 0 1 0 1H1A1 1 0 0 0 2 15h.5a.5.5 0 0 1 0 1H2a2 2 0 0 1-2-2V9a2 2 0 0 1 2-2h1V6h-.5a.5.5 0 0 1 0-1H3v1z"/>',
'bullseye': '<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/><path d="M8 13A5 5 0 1 1 8 3a5 5 0 0 1 0 10zm0 1A6 6 0 1 0 8 2a6 6 0 0 0 0 12z"/><path d="M8 11a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm0 1a4 4 0 1 0 0-8 4 4 0 0 0 0 8z"/><path d="M9.5 8a1.5 1.5 0 1 1-3 0 1.5 1.5 0 0 1 3 0z"/>',
'person-fill-exclamation': '<path d="M11 5a3 3 0 1 1-6 0 3 3 0 0 1 6 0Zm-9 8c0 1 1 1 1 1h5.256A4.493 4.493 0 0 1 8 12.5a4.49 4.49 0 0 1 1.544-3.393C9.077 9.038 8.564 9 8 9c-5 0-6 3-6 4Z"/><path d="M16 12.5a3.5 3.5 0 1 1-7 0 3.5 3.5 0 0 1 7 0Zm-3.5-2a.5.5 0 0 0-.5.5v1.5a.5.5 0 0 0 1 0V11a.5.5 0 0 0-.5-.5Zm0 4a.5.5 0 1 0 0-1 .5.5 0 0 0 0 1Z"/>',
'megaphone-fill': '<path d="M13 2.5a1.5 1.5 0 0 1 3 0v11a1.5 1.5 0 0 1-3 0v-11zm-1 .724c-2.067.95-4.539 1.481-7 1.656v6.237a25.222 25.222 0 0 1 1.088.085c2.053.204 4.038.668 5.912 1.56V3.224zm-8 7.841V4.934c-.68.027-1.399.043-2.008.053A2.02 2.02 0 0 0 0 7v2c0 1.106.896 1.996 1.994 2.009a68.14 68.14 0 0 1 .496.008 64 64 0 0 1 1.51.048zm1.39 1.081c.285.021.569.047.85.078l.253 1.69a1 1 0 0 1-.983 1.187h-.548a1 1 0 0 1-.916-.599l-1.314-2.48a65.81 65.81 0 0 1 1.692.064c.327.017.65.037.966.06z"/>',
'hdd-network-fill': '<path d="M2 2a2 2 0 0 0-2 2v1a2 2 0 0 0 2 2h5.5v3A1.5 1.5 0 0 0 6 11.5H.5a.5.5 0 0 0 0 1H6A1.5 1.5 0 0 0 7.5 14h1a1.5 1.5 0 0 0 1.5-1.5h5.5a.5.5 0 0 0 0-1H10A1.5 1.5 0 0 0 8.5 10V7H14a2 2 0 0 0 2-2V4a2 2 0 0 0-2-2H2zm.5 3a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1zm2 0a.5.5 0 1 1 0-1 .5.5 0 0 1 0 1z"/>',
'tools': '<path d="M1 0L0 1l2.2 3.081a1 1 0 0 0 .815.419h.07a1 1 0 0 1 .708.293l2.675 2.675-2.617 2.654A3.003 3.003 0 0 0 0 13a3 3 0 1 0 5.878-.851l2.654-2.617.968.968-.305.914a1 1 0 0 0 .242 1.023l3.27 3.27a.997.997 0 0 0 1.414 0l1.586-1.586a.997.997 0 0 0 0-1.414l-3.27-3.27a1 1 0 0 0-1.023-.242L10.5 9.5l-.96-.96 2.68-2.643A3.005 3.005 0 0 0 16 3c0-.269-.035-.53-.102-.777l-2.14 2.141L12 4l-.364-1.757L13.777.102a3 3 0 0 0-3.675 3.68L7.462 6.46 4.793 3.793a1 1 0 0 1-.293-.707v-.071a1 1 0 0 0-.419-.814L1 0Zm9.646 10.646a.5.5 0 0 1 .708 0l2.914 2.915a.5.5 0 0 1-.707.707l-2.915-2.914a.5.5 0 0 1 0-.708ZM3 11l.471.242.529.026.287.445.445.287.026.529L5 13l-.242.471-.026.529-.445.287-.287.445-.529.026L3 15l-.471-.242L2 14.732l-.287-.445L1.268 14l-.026-.529L1 13l.242-.471.026-.529.445-.287.287-.445.529-.026L3 11Z"/>',
'shield-exclamation': '<path d="M5.338 1.59a61.44 61.44 0 0 0-2.837.856.481.481 0 0 0-.328.39c-.554 4.157.726 7.19 2.253 9.188a10.725 10.725 0 0 0 2.287 2.233c.346.244.652.42.893.533.12.057.218.095.293.118a.55.55 0 0 0 .101.025.615.615 0 0 0 .1-.025c.076-.023.174-.061.294-.118.24-.113.547-.29.893-.533a10.726 10.726 0 0 0 2.287-2.233c1.527-1.997 2.807-5.031 2.253-9.188a.48.48 0 0 0-.328-.39c-.651-.213-1.75-.56-2.837-.855C9.552 1.29 8.531 1.067 8 1.067c-.53 0-1.552.223-2.662.524zM5.072.56C6.157.265 7.31 0 8 0s1.843.265 2.928.56c1.11.3 2.229.655 2.887.87a1.54 1.54 0 0 1 1.044 1.262c.596 4.477-.787 7.795-2.465 9.99a11.775 11.775 0 0 1-2.517 2.453 7.159 7.159 0 0 1-1.048.625c-.28.132-.581.24-.829.24s-.548-.108-.829-.24a7.158 7.158 0 0 1-1.048-.625 11.777 11.777 0 0 1-2.517-2.453C1.928 10.487.545 7.169 1.141 2.692A1.54 1.54 0 0 1 2.185 1.43 62.456 62.456 0 0 1 5.072.56z"/><path d="M7.001 11a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 4.995a.905.905 0 1 1 1.8 0l-.35 3.507a.553.553 0 0 1-1.1 0L7.1 4.995z"/>',
'person-badge-fill': '<path d="M2 2a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v12a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V2zm4.5 0a.5.5 0 0 0 0 1h3a.5.5 0 0 0 0-1h-3zM8 11a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm5 2.755C12.146 12.825 10.623 12 8 12s-4.146.826-5 1.755V14a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1v-.245z"/>',
'geo-alt-fill': '<path d="M8 16s6-5.686 6-10A6 6 0 0 0 2 6c0 4.314 6 10 6 10zm0-7a3 3 0 1 1 0-6 3 3 0 0 1 0 6z"/>',
'diagram-3-fill': '<path fill-rule="evenodd" d="M6 3.5A1.5 1.5 0 0 1 7.5 2h1A1.5 1.5 0 0 1 10 3.5v1A1.5 1.5 0 0 1 8.5 6v1H14a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0V8h-5v.5a.5.5 0 0 1-1 0v-1A.5.5 0 0 1 2 7h5.5V6A1.5 1.5 0 0 1 6 4.5v-1zm-6 8A1.5 1.5 0 0 1 1.5 10h1A1.5 1.5 0 0 1 4 11.5v1A1.5 1.5 0 0 1 2.5 14h-1A1.5 1.5 0 0 1 0 12.5v-1zm6 0A1.5 1.5 0 0 1 7.5 10h1a1.5 1.5 0 0 1 1.5 1.5v1A1.5 1.5 0 0 1 8.5 14h-1A1.5 1.5 0 0 1 6 12.5v-1zm6 0a1.5 1.5 0 0 1 1.5-1.5h1a1.5 1.5 0 0 1 1.5 1.5v1a1.5 1.5 0 0 1-1.5 1.5h-1a1.5 1.5 0 0 1-1.5-1.5v-1z"/>',
'shield-check': '<path d="M5.338 1.59a61.44 61.44 0 0 0-2.837.856.481.481 0 0 0-.328.39c-.554 4.157.726 7.19 2.253 9.188a10.725 10.725 0 0 0 2.287 2.233c.346.244.652.42.893.533.12.057.218.095.293.118a.55.55 0 0 0 .101.025.615.615 0 0 0 .1-.025c.076-.023.174-.061.294-.118.24-.113.547-.29.893-.533a10.726 10.726 0 0 0 2.287-2.233c1.527-1.997 2.807-5.031 2.253-9.188a.48.48 0 0 0-.328-.39c-.651-.213-1.75-.56-2.837-.855C9.552 1.29 8.531 1.067 8 1.067c-.53 0-1.552.223-2.662.524zM5.072.56C6.157.265 7.31 0 8 0s1.843.265 2.928.56c1.11.3 2.229.655 2.887.87a1.54 1.54 0 0 1 1.044 1.262c.596 4.477-.787 7.795-2.465 9.99a11.775 11.775 0 0 1-2.517 2.453 7.159 7.159 0 0 1-1.048.625c-.28.132-.581.24-.829.24s-.548-.108-.829-.24a7.158 7.158 0 0 1-1.048-.625 11.777 11.777 0 0 1-2.517-2.453C1.928 10.487.545 7.169 1.141 2.692A1.54 1.54 0 0 1 2.185 1.43 62.456 62.456 0 0 1 5.072.56z"/><path d="M10.854 5.146a.5.5 0 0 1 0 .708l-3 3a.5.5 0 0 1-.708 0l-1.5-1.5a.5.5 0 1 1 .708-.708L7.5 7.793l2.646-2.647a.5.5 0 0 1 .708 0z"/>',
'file-earmark-text-fill': '<path d="M9.293 0H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V4.707A1 1 0 0 0 13.707 4L10 .293A1 1 0 0 0 9.293 0zM9.5 3.5v-2l3 3h-2a1 1 0 0 1-1-1zM4.5 9a.5.5 0 0 1 0-1h7a.5.5 0 0 1 0 1h-7zM4 10.5a.5.5 0 0 1 .5-.5h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1-.5-.5zm.5 2.5a.5.5 0 0 1 0-1h4a.5.5 0 0 1 0 1h-4z"/>',
'sticky-fill': '<path d="M2.5 1A1.5 1.5 0 0 0 1 2.5v11A1.5 1.5 0 0 0 2.5 15h6.086a1.5 1.5 0 0 0 1.06-.44l4.915-4.914A1.5 1.5 0 0 0 15 8.586V2.5A1.5 1.5 0 0 0 13.5 1h-11zm6 8.5a1 1 0 0 1 1-1h4.396a.25.25 0 0 1 .177.427l-5.146 5.146a.25.25 0 0 1-.427-.177V9.5z"/>',
'chat-square-text-fill': '<path d="M0 2a2 2 0 0 1 2-2h12a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-2.5a1 1 0 0 0-.8.4l-1.9 2.533a1 1 0 0 1-1.6 0L5.3 12.4a1 1 0 0 0-.8-.4H2a2 2 0 0 1-2-2V2zm3.5 1a.5.5 0 0 0 0 1h9a.5.5 0 0 0 0-1h-9zm0 2.5a.5.5 0 0 0 0 1h9a.5.5 0 0 0 0-1h-9zm0 2.5a.5.5 0 0 0 0 1h5a.5.5 0 0 0 0-1h-5z"/>',
'eye-fill': '<path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0z"/><path d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8zm8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7z"/>',
'folder-fill': '<path d="M9.828 3h3.982a2 2 0 0 1 1.992 2.181l-.637 7A2 2 0 0 1 13.174 14H2.825a2 2 0 0 1-1.991-1.819l-.637-7a1.99 1.99 0 0 1 .342-1.31L.5 3a2 2 0 0 1 2-2h3.672a2 2 0 0 1 1.414.586l.828.828A2 2 0 0 0 9.828 3zm-8.322.12C1.72 3.042 1.95 3 2.19 3h5.396l-.707-.707A1 1 0 0 0 6.172 2H2.5a1 1 0 0 0-1 .981l.006.139z"/>',
'exclamation-triangle-fill': '<path d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z"/>'
};

// Generate SVG data URI for icon
function getIconSvg(iconName, color = 'white') {
const path = iconPaths[iconName] || iconPaths['crosshair'];
return `data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="${color}" viewBox="0 0 16 16">${path}</svg>`)}`;
}

function getIconForType(type) {
const iconName = typeIcons[type] || typeIcons[type.replace('-', '_')] || 'crosshair';
return getIconSvg(iconName);
}

// STIX type colors (harmonized with /stix/graph)
const stixTypeColors = {
'indicator': '#FF6B6B',
'malware': '#e74c3c',
'threat-actor': '#2c3e50',
'attack-pattern': '#9b59b6',
'campaign': '#f39c12',
'tool': '#3498db',
'vulnerability': '#e67e22',
'infrastructure': '#1abc9c',
'intrusion-set': '#8e44ad',
'identity': '#27ae60',
'location': '#16a085',
'course-of-action': '#2ecc71',
'note': '#95a5a6',
'opinion': '#bdc3c7',
'report': '#34495e',
'observed-data': '#1abc9c',
'grouping': '#7f8c8d'
};

fetch(`/api/cases/${caseId}/graph-data`)
.then(response => response.json())
.then(data => {
Expand All @@ -1462,20 +1522,25 @@ <h6 class="mb-1"><strong>${escapeHtml(inc.title)}</strong></h6>
}

// Add colors for nodes
const getColorForEntity = (type) => {
const colors = {
'stix': '#17a2b8',
'ioc': '#0dcaf0',
'case': '#0d6efd',
'incident': '#dc3545',
'user': '#6c757d'
};
return colors[type] || '#888';
const getColorForEntity = (entityType, stixType) => {
if (entityType === 'case') return '#3498db';
if (entityType === 'incident') return '#e74c3c';
// For STIX objects, use specific STIX type color
if (stixType && stixTypeColors[stixType]) {
return stixTypeColors[stixType];
}
// Try with underscore replacement
if (stixType && stixTypeColors[stixType.replace('-', '_')]) {
return stixTypeColors[stixType.replace('-', '_')];
}
return '#FF6B6B'; // Default indicator color
};

data.nodes.forEach(node => {
const type = node.data.entity_type || 'stix';
node.data.color = getColorForEntity(type);
const stixType = node.data.stix_type || node.data.type || type;
node.data.color = getColorForEntity(type, stixType);
node.data.icon = getIconForType(stixType);
});

initCaseGraph(data.nodes, data.edges, caseId);
Expand Down
4 changes: 2 additions & 2 deletions templates/dashboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ <h3 class="mb-0">{{ total_checklists }}</h3>
</div>

<!-- My Assignments -->
<div class="row g-4 mt-4">
<div class="row g-4 mt-4 mb-4">
<!-- Assigned Cases -->
<div class="col-md-4">
<div class="card h-100">
Expand Down Expand Up @@ -269,7 +269,7 @@ <h6 class="mb-0">
{% endif %}

<!-- Secondary Stats -->
<div class="row g-4 mb-4">
<div class="row g-4 mb-4 mt-4">
<!-- STIX Objects by Type -->
<div class="col-md-3">
<div class="card h-100">
Expand Down
Loading
Loading