change framework

This commit is contained in:
2025-07-14 10:11:42 +02:00
parent d90b345819
commit 921abfb5b9
32 changed files with 6736 additions and 3848 deletions

53
src/pages/about.astro Normal file
View File

@@ -0,0 +1,53 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
---
<BaseLayout title="About">
<section style="padding: 2rem 0; max-width: 800px; margin: 0 auto;">
<h1 style="text-align: center; margin-bottom: 2rem;">About DFIR Tools Hub</h1>
<div class="card" style="margin-bottom: 2rem;">
<h2>Project Overview</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</p>
<p>
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
</div>
<div class="card" style="margin-bottom: 2rem;">
<h2>DFIR Methodology</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit:</p>
<ul style="margin-left: 1.5rem; margin-bottom: 1rem;">
<li><strong>Data Collection:</strong> Lorem ipsum dolor sit amet</li>
<li><strong>Examination:</strong> Consectetur adipiscing elit</li>
<li><strong>Analysis:</strong> Sed do eiusmod tempor incididunt</li>
<li><strong>Reporting:</strong> Ut labore et dolore magna aliqua</li>
</ul>
</div>
<div class="card" style="margin-bottom: 2rem;">
<h2>Forensic Domains</h2>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit:</p>
<ul style="margin-left: 1.5rem;">
<li>Storage & File System Artifacts</li>
<li>Memory & Runtime Artifacts</li>
<li>Network & Communication Artifacts</li>
<li>Application & Code Artifacts</li>
<li>Multimedia & Content Artifacts</li>
<li>Transaction & Financial Artifacts</li>
<li>Platform & Infrastructure Artifacts</li>
</ul>
</div>
<div class="card">
<h2>Contributing</h2>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
Visit our <a href="https://github.com/your-org/dfir-tools-hub" target="_blank" rel="noopener noreferrer">GitHub repository</a>
to contribute or report issues.
</p>
</div>
</section>
</BaseLayout>

163
src/pages/index.astro Normal file
View File

@@ -0,0 +1,163 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import ToolCard from '../components/ToolCard.astro';
import ToolFilters from '../components/ToolFilters.astro';
import ToolMatrix from '../components/ToolMatrix.astro';
import { promises as fs } from 'fs';
import { load } from 'js-yaml';
import path from 'path';
// Load tools data
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
const yamlContent = await fs.readFile(yamlPath, 'utf8');
const data = load(yamlContent) as any;
const tools = data.tools;
---
<BaseLayout title="Home">
<!-- Hero Section -->
<section style="text-align: center; padding: 3rem 0; border-bottom: 1px solid var(--color-border);">
<h1 style="margin-bottom: 1rem;">DFIR Tools Hub</h1>
<p class="text-muted" style="font-size: 1.125rem; max-width: 800px; margin: 0 auto;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation.
</p>
</section>
<!-- Filters Section -->
<section style="padding: 2rem 0;">
<ToolFilters />
</section>
<!-- Tools Grid -->
<section id="tools-grid" style="padding-bottom: 2rem;">
<div class="grid grid-cols-3 gap-4" id="tools-container">
{tools.map((tool: any) => (
<ToolCard tool={tool} />
))}
</div>
<!-- No results message -->
<div id="no-results" style="display: none; text-align: center; padding: 4rem 0;">
<p class="text-muted" style="font-size: 1.125rem;">No tools found matching your criteria.</p>
</div>
</section>
<!-- Matrix View -->
<ToolMatrix />
</BaseLayout>
<script>
// Handle view changes and filtering
document.addEventListener('DOMContentLoaded', () => {
const toolsContainer = document.getElementById('tools-container');
const toolsGrid = document.getElementById('tools-grid');
const matrixContainer = document.getElementById('matrix-container');
const noResults = document.getElementById('no-results');
// Initial tools HTML
const initialToolsHTML = toolsContainer.innerHTML;
// Handle filtered results
window.addEventListener('toolsFiltered', (event) => {
const filtered = event.detail;
const currentView = document.querySelector('.view-toggle.active')?.getAttribute('data-view');
if (currentView === 'matrix') {
// Matrix view handles its own rendering
return;
}
// Clear container
toolsContainer.innerHTML = '';
if (filtered.length === 0) {
noResults.style.display = 'block';
} else {
noResults.style.display = 'none';
// Render filtered tools
filtered.forEach(tool => {
const toolCard = createToolCard(tool);
toolsContainer.appendChild(toolCard);
});
}
});
// Handle view changes
window.addEventListener('viewChanged', (event) => {
const view = event.detail;
if (view === 'matrix') {
toolsGrid.style.display = 'none';
matrixContainer.style.display = 'block';
} else {
toolsGrid.style.display = 'block';
matrixContainer.style.display = 'none';
}
});
// Create tool card element
function createToolCard(tool) {
const cardDiv = document.createElement('div');
const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card');
cardDiv.className = cardClass;
cardDiv.innerHTML = `
<div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 0.75rem;">
<h3 style="margin: 0;">${tool.name}</h3>
<div style="display: flex; gap: 0.5rem;">
${tool.isHosted ? '<span class="badge badge-primary">Self-Hosted</span>' : ''}
${tool.license !== 'Proprietary' ? '<span class="badge badge-success">Open Source</span>' : ''}
</div>
</div>
<p class="text-muted" style="font-size: 0.875rem; margin-bottom: 1rem;">
${tool.description}
</p>
<div style="display: flex; flex-wrap: wrap; gap: 0.5rem; margin-bottom: 1rem;">
<div style="display: flex; align-items: center; gap: 0.25rem;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect>
<line x1="9" y1="9" x2="15" y2="9"></line>
<line x1="9" y1="15" x2="15" y2="15"></line>
</svg>
<span class="text-muted" style="font-size: 0.75rem;">
${tool.platforms.join(', ')}
</span>
</div>
<div style="display: flex; align-items: center; gap: 0.25rem;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<circle cx="12" cy="12" r="10"></circle>
<path d="M12 6v6l4 2"></path>
</svg>
<span class="text-muted" style="font-size: 0.75rem;">
${tool.skillLevel}
</span>
</div>
<div style="display: flex; align-items: center; gap: 0.25rem;">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"></path>
<polyline points="14 2 14 8 20 8"></polyline>
</svg>
<span class="text-muted" style="font-size: 0.75rem;">
${tool.license}
</span>
</div>
</div>
<div style="display: flex; flex-wrap: wrap; gap: 0.25rem; margin-bottom: 1rem;">
${tool.tags.map(tag => `<span class="tag">${tag}</span>`).join('')}
</div>
<a href="${tool.url}" target="_blank" rel="noopener noreferrer" class="btn btn-primary" style="width: 100%;">
${tool.isHosted ? 'Access Service' : 'Visit Website'}
</a>
`;
return cardDiv;
}
});
</script>

83
src/pages/status.astro Normal file
View File

@@ -0,0 +1,83 @@
---
import BaseLayout from '../layouts/BaseLayout.astro';
import { promises as fs } from 'fs';
import { load } from 'js-yaml';
import path from 'path';
// Load tools data to get self-hosted services
const yamlPath = path.join(process.cwd(), 'src/data/tools.yaml');
const yamlContent = await fs.readFile(yamlPath, 'utf8');
const data = load(yamlContent) as any;
const hostedServices = data.tools.filter((tool: any) => tool.isHosted);
---
<BaseLayout title="Service Status">
<section style="padding: 2rem 0;">
<h1 style="text-align: center; margin-bottom: 1rem;">Service Status</h1>
<p class="text-muted" style="text-align: center; max-width: 600px; margin: 0 auto 3rem;">
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Real-time monitoring of our self-hosted DFIR services.
</p>
<!-- Service Status Grid -->
<div class="grid grid-cols-2 gap-4" style="margin-bottom: 3rem;">
{hostedServices.map((service: any) => (
<div class="card">
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 1rem;">
<h3 style="margin: 0;">{service.name}</h3>
<div id={`status-${service.name.toLowerCase().replace(/\s+/g, '-')}`}>
<!-- Status badge will be inserted here -->
<span class="badge badge-warning">Loading...</span>
</div>
</div>
<p class="text-muted" style="font-size: 0.875rem; margin-bottom: 1rem;">
{service.description}
</p>
<a href={service.url} target="_blank" rel="noopener noreferrer" class="btn btn-secondary">
Access Service →
</a>
</div>
))}
</div>
<!-- Uptime Kuma Embed -->
<div class="card" style="padding: 0; overflow: hidden;">
<iframe
src="https://uptime.example.lab/status/lab-services"
style="width: 100%; height: 600px; border: none;"
title="Uptime Kuma Status Page"
></iframe>
</div>
</section>
</BaseLayout>
<script define:vars={{ hostedServices }}>
// Fetch status for each service
document.addEventListener('DOMContentLoaded', async () => {
for (const service of hostedServices) {
if (service.statusUrl) {
try {
// Fetch status badge/API endpoint
const response = await fetch(service.statusUrl);
const data = await response.json();
// Update status badge
const statusElement = document.getElementById(`status-${service.name.toLowerCase().replace(/\s+/g, '-')}`);
if (statusElement) {
const isUp = data.status === 'up' || data.status === 1;
statusElement.innerHTML = `
<span class="badge ${isUp ? 'badge-success' : 'badge-error'}">
${isUp ? 'Operational' : 'Down'}
</span>
`;
}
} catch (error) {
console.error(`Failed to fetch status for ${service.name}:`, error);
const statusElement = document.getElementById(`status-${service.name.toLowerCase().replace(/\s+/g, '-')}`);
if (statusElement) {
statusElement.innerHTML = '<span class="badge badge-warning">Unknown</span>';
}
}
}
}
});
</script>