content overhaul

This commit is contained in:
overcuriousity
2025-07-28 10:46:17 +02:00
parent b1834aace1
commit 81bbafeef1
5 changed files with 2354 additions and 232 deletions

View File

@@ -526,7 +526,7 @@
</div>
<div class="form-group">
<label>Scenarios</label>
<label>🎮 Scenario Tags <small style="color: #666;">(adds scenario: prefix to tags)</small></label>
<div id="scenariosCheckbox" class="checkbox-group"></div>
</div>
</div>
@@ -777,11 +777,14 @@
{ id: 'specific-os', name: 'Betriebssysteme', description: 'Operating Systems which focus on forensics' }
],
scenarios: [
{ id: 'registry', icon: '🗃️', friendly_name: 'Registry-Analyse' },
{ id: 'memory-forensics', icon: '🧠', friendly_name: 'Memory-Forensik' },
{ id: 'network-analysis', icon: '🌐', friendly_name: 'Netzwerk-Analyse' },
{ id: 'malware-analysis', icon: '🦠', friendly_name: 'Malware-Analyse' },
{ id: 'mobile-forensics', icon: '📱', friendly_name: 'Mobile-Forensik' }
{ id: 'scenario:disk_imaging', icon: '💽', friendly_name: 'Datenträgerabbild' },
{ id: 'scenario:memory_dump', icon: '🧠', friendly_name: 'RAM-Analyse' },
{ id: 'scenario:file_recovery', icon: '🗑️', friendly_name: 'Datenrettung' },
{ id: 'scenario:browser_history', icon: '🌍', friendly_name: 'Browser-Spuren' },
{ id: 'scenario:credential_theft', icon: '🛑', friendly_name: 'Zugangsdiebstahl' },
{ id: 'scenario:remote_access', icon: '📡', friendly_name: 'Fernzugriffe' },
{ id: 'scenario:persistence', icon: '♻️', friendly_name: 'Persistenzsuche' },
{ id: 'scenario:windows-registry', icon: '📜', friendly_name: 'Registry-Analyse' }
]
};
@@ -819,7 +822,7 @@
// Search in description
if (tool.description && tool.description.toLowerCase().includes(term)) return true;
// Search in tags
// Search in tags (includes scenarios as scenario: prefixed tags)
if (tool.tags && tool.tags.some(tag => tag.toLowerCase().includes(term))) return true;
// Search in related concepts
@@ -828,10 +831,13 @@
// Search in related software
if (tool.related_software && tool.related_software.some(software => software.toLowerCase().includes(term))) return true;
// Search in scenarios
if (tool.scenarios && tool.scenarios.some(scenario => {
const scenarioData = yamlData.scenarios.find(s => s.id === scenario);
return scenarioData && scenarioData.friendly_name.toLowerCase().includes(term);
// Search in scenario friendly names (from tags that start with scenario:)
if (tool.tags && tool.tags.some(tag => {
if (tag.startsWith('scenario:')) {
const scenarioData = yamlData.scenarios.find(s => s.id === tag);
return scenarioData && scenarioData.friendly_name.toLowerCase().includes(term);
}
return false;
})) return true;
// Search in type
@@ -1052,16 +1058,15 @@
const icon = document.getElementById('toolIcon').value.trim();
if (icon) tool.icon = icon;
// Add domains, phases, and scenarios
// Add domains, phases
tool.domains = getCheckedValues('#domainsCheckbox input:checked');
tool.phases = getCheckedValues('#phasesCheckbox input:checked');
const scenarios = getCheckedValues('#scenariosCheckbox input:checked');
if (scenarios.length > 0) tool.scenarios = scenarios;
// Add tags, related concepts, and related software
// Add tags and scenario tags (scenarios get added to tags with scenario: prefix)
const tags = getTags();
if (tags.length > 0) tool.tags = tags;
const scenarioTags = getCheckedValues('#scenariosCheckbox input:checked');
const allTags = [...tags, ...scenarioTags];
if (allTags.length > 0) tool.tags = allTags;
const relatedConcepts = getRelatedConcepts();
if (relatedConcepts.length > 0) tool.related_concepts = relatedConcepts;
@@ -1118,9 +1123,19 @@
function clearForm() {
document.getElementById('toolForm').reset();
// Clear all tag inputs properly
document.getElementById('tagsInput').innerHTML = '<input type="text" id="tagInputField" placeholder="Add tags..." onkeydown="handleTagInput(event)" style="border: none; outline: none; flex: 1; min-width: 100px;">';
document.getElementById('relatedConceptsInput').innerHTML = '<input type="text" id="relatedConceptInputField" placeholder="Add concept names..." onkeydown="handleRelatedConceptInput(event)" style="border: none; outline: none; flex: 1; min-width: 100px;">';
document.getElementById('relatedSoftwareInput').innerHTML = '<input type="text" id="relatedSoftwareInputField" placeholder="Add software names..." onkeydown="handleRelatedSoftwareInput(event)" style="border: none; outline: none; flex: 1; min-width: 100px;">';
// Clear all checkboxes
document.querySelectorAll('#domainsCheckbox input[type="checkbox"]').forEach(cb => cb.checked = false);
document.querySelectorAll('#phasesCheckbox input[type="checkbox"]').forEach(cb => cb.checked = false);
document.querySelectorAll('#scenariosCheckbox input[type="checkbox"]').forEach(cb => cb.checked = false);
document.querySelectorAll('#platformsCheckbox input[type="checkbox"]').forEach(cb => cb.checked = false);
document.querySelectorAll('#domainAgnosticCheckbox input[type="checkbox"]').forEach(cb => cb.checked = false);
currentEditingIndex = -1;
toggleConditionalFields();
}
@@ -1155,14 +1170,21 @@
// Set checkboxes
setCheckboxValues('#domainsCheckbox input', tool.domains || []);
setCheckboxValues('#phasesCheckbox input', tool.phases || []);
setCheckboxValues('#scenariosCheckbox input', tool.scenarios || []);
setCheckboxValues('#platformsCheckbox input', tool.platforms || []);
setCheckboxValues('#domainAgnosticCheckbox input', tool['domain-agnostic-software'] || []);
// Set tags
// Separate scenario tags from regular tags
const allTags = tool.tags || [];
const scenarioTags = allTags.filter(tag => tag.startsWith('scenario:'));
const regularTags = allTags.filter(tag => !tag.startsWith('scenario:'));
// Set scenario checkboxes based on scenario tags
setCheckboxValues('#scenariosCheckbox input', scenarioTags);
// Set regular tags
const tagsContainer = document.getElementById('tagsInput');
tagsContainer.innerHTML = '<input type="text" id="tagInputField" placeholder="Add tags..." onkeydown="handleTagInput(event)" style="border: none; outline: none; flex: 1; min-width: 100px;">';
(tool.tags || []).forEach(tag => addTag('tagsInput', tag));
regularTags.forEach(tag => addTag('tagsInput', tag));
// Set related concepts
const conceptsContainer = document.getElementById('relatedConceptsInput');
@@ -1241,10 +1263,11 @@
const card = document.createElement('div');
card.className = `tool-card ${tool.type || 'software'}`;
const tags = (tool.tags || []).map(tag => `<span class="tag">${tag}</span>`).join('');
const tags = (tool.tags || []).filter(tag => !tag.startsWith('scenario:')).map(tag => `<span class="tag">${tag}</span>`).join('');
const knowledgebaseIndicator = tool.knowledgebase ? '<span class="tag" style="background: #e8f5e8; color: #27ae60;">📚 KB</span>' : '';
const relatedSoftwareIndicator = (tool.related_software && tool.related_software.length > 0) ? '<span class="tag" style="background: #e3f2fd; color: #1976d2;">🔗 SW</span>' : '';
const scenariosIndicator = (tool.scenarios && tool.scenarios.length > 0) ? '<span class="tag" style="background: #f3e5f5; color: #7b1fa2;">🎮 SC</span>' : '';
const scenarioTags = (tool.tags || []).filter(tag => tag.startsWith('scenario:'));
const scenariosIndicator = scenarioTags.length > 0 ? '<span class="tag" style="background: #f3e5f5; color: #7b1fa2;">🎮 SC</span>' : '';
card.innerHTML = `
<h3>${tool.icon ? tool.icon + ' ' : ''}${tool.name} <span style="font-size: 0.7em; color: #666;">[${tool.type || 'software'}]</span></h3>
@@ -1294,7 +1317,10 @@
const indicators = [];
if (tool.knowledgebase) indicators.push('📚');
if (tool.related_software?.length > 0) indicators.push('🔗');
if (tool.scenarios?.length > 0) indicators.push('🎮');
// Check for scenario tags
const scenarioTags = (tool.tags || []).filter(tag => tag.startsWith('scenario:'));
if (scenarioTags.length > 0) indicators.push('🎮');
card.innerHTML = `
<div style="display: flex; align-items: center; gap: 10px; margin-bottom: 10px;">
@@ -1517,17 +1543,20 @@
}
}
// NEW: Scenario operations
// Scenario operations (work with tags that have scenario: prefix)
function bulkAddScenarios() {
if (selectedTools.size === 0) return showMessage('No tools selected', 'error');
const scenarios = prompt('Enter scenario IDs to add (comma-separated):');
const scenarios = prompt('Enter scenario IDs to add (comma-separated, e.g., scenario:memory_dump,scenario:registry):');
if (scenarios) {
const scenarioList = scenarios.split(',').map(s => s.trim()).filter(s => s);
const scenarioList = scenarios.split(',').map(s => {
const trimmed = s.trim();
return trimmed.startsWith('scenario:') ? trimmed : `scenario:${trimmed}`;
}).filter(s => s !== 'scenario:');
selectedTools.forEach(index => {
const tool = yamlData.tools[index];
tool.scenarios = [...new Set([...(tool.scenarios || []), ...scenarioList])];
tool.tags = [...new Set([...(tool.tags || []), ...scenarioList])];
});
showMessage(`Added scenarios to ${selectedTools.size} tools`);
showMessage(`Added scenario tags to ${selectedTools.size} tools`);
renderBulkGrid();
}
}
@@ -1536,26 +1565,33 @@
if (selectedTools.size === 0) return showMessage('No tools selected', 'error');
const scenarios = prompt('Enter scenario IDs to remove (comma-separated):');
if (scenarios) {
const scenarioList = scenarios.split(',').map(s => s.trim()).filter(s => s);
const scenarioList = scenarios.split(',').map(s => {
const trimmed = s.trim();
return trimmed.startsWith('scenario:') ? trimmed : `scenario:${trimmed}`;
}).filter(s => s !== 'scenario:');
selectedTools.forEach(index => {
const tool = yamlData.tools[index];
if (tool.scenarios) {
tool.scenarios = tool.scenarios.filter(scenario => !scenarioList.includes(scenario));
if (tool.scenarios.length === 0) delete tool.scenarios;
if (tool.tags) {
tool.tags = tool.tags.filter(tag => !scenarioList.includes(tag));
if (tool.tags.length === 0) delete tool.tags;
}
});
showMessage(`Removed scenarios from ${selectedTools.size} tools`);
showMessage(`Removed scenario tags from ${selectedTools.size} tools`);
renderBulkGrid();
}
}
function bulkClearScenarios() {
if (selectedTools.size === 0) return showMessage('No tools selected', 'error');
if (confirm(`Are you sure you want to clear ALL scenarios from ${selectedTools.size} selected tools?`)) {
if (confirm(`Are you sure you want to clear ALL scenario tags from ${selectedTools.size} selected tools?`)) {
selectedTools.forEach(index => {
delete yamlData.tools[index].scenarios;
const tool = yamlData.tools[index];
if (tool.tags) {
tool.tags = tool.tags.filter(tag => !tag.startsWith('scenario:'));
if (tool.tags.length === 0) delete tool.tags;
}
});
showMessage(`Cleared scenarios from ${selectedTools.size} tools`);
showMessage(`Cleared scenario tags from ${selectedTools.size} tools`);
renderBulkGrid();
}
}
@@ -1769,12 +1805,15 @@ ${tool.domains && tool.domains.length > 0 ? `## Anwendungsbereiche
${tool.domains.map(domain => `- ${domain}`).join('\n')}\n\n` : ''}${tool.phases && tool.phases.length > 0 ? `## Ermittlungsphasen
${tool.phases.map(phase => `- ${phase}`).join('\n')}\n\n` : ''}${tool.scenarios && tool.scenarios.length > 0 ? `## Anwendungsszenarien
${tool.phases.map(phase => `- ${phase}`).join('\n')}\n\n` : ''}${(() => {
const scenarioTags = (tool.tags || []).filter(tag => tag.startsWith('scenario:'));
return scenarioTags.length > 0 ? `## Anwendungsszenarien
${tool.scenarios.map(scenario => {
const scenarioData = yamlData.scenarios.find(s => s.id === scenario);
return scenarioData ? `- ${scenarioData.icon} ${scenarioData.friendly_name}` : `- ${scenario}`;
}).join('\n')}\n\n` : ''}## ${tool.type === 'concept' ? 'Grundlagen' : tool.type === 'method' ? 'Vorgehensweise' : 'Installation & Nutzung'}
${scenarioTags.map(scenarioTag => {
const scenarioData = yamlData.scenarios.find(s => s.id === scenarioTag);
return scenarioData ? `- ${scenarioData.icon} ${scenarioData.friendly_name}` : `- ${scenarioTag}`;
}).join('\n')}\n\n` : '';
})()}## ${tool.type === 'concept' ? 'Grundlagen' : tool.type === 'method' ? 'Vorgehensweise' : 'Installation & Nutzung'}
${tool.type === 'concept' ?
`### Kernkonzepte
@@ -1863,7 +1902,7 @@ TODO: Füge weitere nützliche Links und Ressourcen hinzu.
});
}
// Enhanced Validation including scenarios and related_software
// Enhanced Validation
function validateYAML() {
if (!yamlData) return showMessage('No data to validate', 'error');
@@ -1873,7 +1912,7 @@ TODO: Füge weitere nützliche Links und Ressourcen hinzu.
if (!yamlData.tools) validationResults.push('❌ Missing tools section');
if (!yamlData.domains) validationResults.push('❌ Missing domains section');
if (!yamlData.phases) validationResults.push('❌ Missing phases section');
if (!yamlData.scenarios) validationResults.push('⚠️ Missing scenarios section');
if (!yamlData.scenarios) validationResults.push('⚠️ Missing scenarios section (for reference)');
// Validate tools
yamlData.tools?.forEach((tool, index) => {
@@ -1904,12 +1943,13 @@ TODO: Füge weitere nützliche Links und Ressourcen hinzu.
});
}
// Validate scenarios references
if (tool.scenarios && tool.scenarios.length > 0) {
tool.scenarios.forEach(scenarioId => {
const exists = yamlData.scenarios?.some(s => s.id === scenarioId);
// Validate scenario tags (check tags that start with scenario:)
if (tool.tags && tool.tags.length > 0) {
const scenarioTags = tool.tags.filter(tag => tag.startsWith('scenario:'));
scenarioTags.forEach(scenarioTag => {
const exists = yamlData.scenarios?.some(s => s.id === scenarioTag);
if (!exists) {
validationResults.push(`⚠️ Tool ${index + 1}: Scenario "${scenarioId}" not found in scenarios`);
validationResults.push(`⚠️ Tool ${index + 1}: Scenario tag "${scenarioTag}" not found in scenarios reference`);
}
});
}