From b842df040cb536050747c5be05784f3555a9eea1 Mon Sep 17 00:00:00 2001 From: overcuriousity Date: Mon, 14 Jul 2025 16:56:06 +0200 Subject: [PATCH] adjust dual urls --- src/components/ToolCard.astro | 32 +++- src/components/ToolMatrix.astro | 256 +++++++++++++++++++++++++------- src/data/tools.yaml | 59 +++++++- src/pages/index.astro | 161 ++++++++++++-------- src/styles/global.css | 69 +++++++++ 5 files changed, 452 insertions(+), 125 deletions(-) diff --git a/src/components/ToolCard.astro b/src/components/ToolCard.astro index e4bf10a..e121f7c 100644 --- a/src/components/ToolCard.astro +++ b/src/components/ToolCard.astro @@ -9,6 +9,7 @@ export interface Props { skillLevel: string; accessType: string; url: string; + projectUrl?: string; license: string; tags: string[]; isHosted: boolean; @@ -20,6 +21,12 @@ const { tool } = Astro.props; // Determine card styling const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card'); + +// Check if tool has a valid project URL for hosted services +const hasValidProjectUrl = tool.projectUrl !== undefined && + tool.projectUrl !== null && + tool.projectUrl !== "" && + tool.projectUrl.trim() !== ""; ---
@@ -74,7 +81,26 @@ const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Propri ))}
- - {tool.isHosted ? 'Access Service' : 'Visit Website'} - + + {tool.isHosted && hasValidProjectUrl ? ( + +
+ + Project Page + + + Access Service + +
+ ) : tool.isHosted ? ( + + + Project Page + + ) : ( + + + Visit Website + + )} \ No newline at end of file diff --git a/src/components/ToolMatrix.astro b/src/components/ToolMatrix.astro index ada2984..b2e2c2f 100644 --- a/src/components/ToolMatrix.astro +++ b/src/components/ToolMatrix.astro @@ -12,12 +12,21 @@ const domains = data.domains; const phases = data.phases; const tools = data.tools; -// Create matrix structure +// Separate collaboration tools from domain-specific tools +const collaborationTools = tools.filter((tool: any) => + tool.phases.includes('collaboration') +); + +const domainTools = tools.filter((tool: any) => + !tool.phases.includes('collaboration') +); + +// Create matrix structure for domain-specific tools only const matrix: Record> = {}; domains.forEach((domain: any) => { matrix[domain.id] = {}; - phases.forEach((phase: any) => { - matrix[domain.id][phase.id] = tools.filter((tool: any) => + phases.filter((phase: any) => phase.id !== 'collaboration').forEach((phase: any) => { + matrix[domain.id][phase.id] = domainTools.filter((tool: any) => tool.domains.includes(domain.id) && tool.phases.includes(phase.id) ); }); @@ -25,36 +34,67 @@ domains.forEach((domain: any) => { --- @@ -78,12 +118,11 @@ domains.forEach((domain: any) => {
- - Visit Website - + + - \ No newline at end of file diff --git a/src/data/tools.yaml b/src/data/tools.yaml index a75e5e9..df75d2f 100644 --- a/src/data/tools.yaml +++ b/src/data/tools.yaml @@ -15,6 +15,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://www.autopsy.com/" + projectUrl: "" license: "Apache 2.0" tags: ["disk-forensics", "file-recovery", "timeline-analysis"] isHosted: false @@ -30,6 +31,7 @@ tools: skillLevel: "advanced" accessType: "download" url: "https://www.volatilityfoundation.org/" + projectUrl: "" license: "VSL" tags: ["memory-forensics", "malware-analysis", "incident-response"] isHosted: false @@ -48,7 +50,8 @@ tools: platforms: ["Web"] skillLevel: "intermediate" accessType: "self-hosted" - url: "https://thehive.example.lab" + url: "https://strangebee.com/" + projectUrl: "" license: "AGPL-3.0" tags: ["incident-response", "case-management", "collaboration"] isHosted: true @@ -66,7 +69,8 @@ tools: platforms: ["Web"] skillLevel: "intermediate" accessType: "self-hosted" - url: "https://misp.example.lab" + url: "https://misp-project.org/" + projectUrl: "https://misp.cc24.dev" license: "AGPL-3.0" tags: ["threat-intelligence", "ioc-sharing", "collaboration"] isHosted: true @@ -83,7 +87,8 @@ tools: platforms: ["Web"] skillLevel: "intermediate" accessType: "self-hosted" - url: "https://timesketch.example.lab" + url: "https://timesketch.org/" + projectUrl: "https://timesketch.cc24.dev" license: "Apache 2.0" tags: ["timeline-analysis", "collaboration", "visualization"] isHosted: true @@ -101,6 +106,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://www.wireshark.org/" + projectUrl: "" license: "GPL-2.0" tags: ["network-analysis", "pcap", "protocol-analysis"] isHosted: false @@ -119,6 +125,7 @@ tools: skillLevel: "advanced" accessType: "commercial" url: "https://www.opentext.com/products/encase-forensic" + projectUrl: "" license: "Proprietary" tags: ["commercial", "enterprise", "court-approved"] isHosted: false @@ -135,6 +142,7 @@ tools: skillLevel: "advanced" accessType: "self-hosted" url: "https://cuckoosandbox.org/" + projectUrl: "" license: "GPL-3.0" tags: ["malware-analysis", "sandbox", "dynamic-analysis"] isHosted: true @@ -151,6 +159,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://exterro.com/ftk-imager" + projectUrl: "" license: "Proprietary" tags: ["disk-imaging", "preview", "data-acquisition"] isHosted: false @@ -167,6 +176,7 @@ tools: skillLevel: "advanced" accessType: "self-hosted" url: "https://github.com/google/grr" + projectUrl: "" license: "Apache 2.0" tags: ["live-forensics", "remote-response", "dfir"] isHosted: true @@ -183,6 +193,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://plaso.readthedocs.io/" + projectUrl: "" license: "Apache 2.0" tags: ["timeline-analysis", "log-parsing", "dfir"] isHosted: false @@ -198,6 +209,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://www.netresec.com/?page=NetworkMiner" + projectUrl: "" license: "Freeware/Commercial" tags: ["pcap-analysis", "passive-sniffing", "credential-recovery"] isHosted: false @@ -214,6 +226,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://www.mandiant.com/resources/download/redline" + projectUrl: "" license: "Proprietary" tags: ["memory-analysis", "ioc-scan", "host-analysis"] isHosted: false @@ -230,6 +243,7 @@ tools: skillLevel: "intermediate" accessType: "download" url: "https://www.kroll.com/en/services/cyber-risk/incident-response-litigation-support/kroll-artifact-parser-extractor-kape" + projectUrl: "" license: "Freeware" tags: ["triage", "artifact-collection", "parsing"] isHosted: false @@ -246,6 +260,7 @@ tools: skillLevel: "advanced" accessType: "self-hosted" url: "https://www.velociraptor.app/" + projectUrl: "" license: "Apache 2.0" tags: ["dfir", "hunting", "endpoint-monitoring"] isHosted: true @@ -262,6 +277,7 @@ tools: skillLevel: "advanced" accessType: "self-hosted" url: "https://arkime.com/" + projectUrl: "" license: "Apache 2.0" tags: ["packet-capture", "full-packet-analysis", "network-forensics"] isHosted: true @@ -279,10 +295,43 @@ tools: skillLevel: "advanced" accessType: "commercial" url: "https://www.x-ways.net/forensics/" + projectUrl: "" license: "Proprietary" tags: ["disk-forensics", "file-recovery", "commercial"] isHosted: false + # Collaboration Tools - Domain-agnostic + - name: "Nextcloud" + description: "Self-hosted file sharing and collaboration platform for secure data exchange" + domains: [] # Domain-agnostic + phases: + - "collaboration" + platforms: ["Web"] + skillLevel: "beginner" + accessType: "self-hosted" + url: "https://nextcloud.com/de/" + projectUrl: "https://cloud.cc24.dev" + license: "AGPL-3.0" + tags: ["file-sharing", "collaboration", "document-management", "secure-storage"] + isHosted: true + statusUrl: "https://uptime.example.lab/api/badge/10/status" + + - name: "Gitea" + description: "Lightweight self-hosted Git service for code collaboration and version control" + domains: [] # Domain-agnostic + phases: + - "collaboration" + platforms: ["Web"] + skillLevel: "intermediate" + accessType: "self-hosted" + url: "https://git.example.lab" + projectUrl: "" + license: "MIT" + tags: ["version-control", "git", "code-collaboration", "documentation"] + isHosted: true + statusUrl: "https://uptime.example.lab/api/badge/11/status" + + # Domain definitions for reference domains: - id: "storage-file-system" @@ -309,4 +358,6 @@ phases: - id: "analysis" name: "Analysis" - id: "reporting" - name: "Reporting" \ No newline at end of file + name: "Reporting" + - id: "collaboration" + name: "General Tools for Collaboration" \ No newline at end of file diff --git a/src/pages/index.astro b/src/pages/index.astro index eac970e..50c81f6 100644 --- a/src/pages/index.astro +++ b/src/pages/index.astro @@ -104,68 +104,107 @@ const tools = data.tools; } }); - // Create tool card element - function createToolCard(tool: any): HTMLElement { - const cardDiv = document.createElement('div'); - const cardClass = tool.isHosted ? 'card card-hosted' : (tool.license !== 'Proprietary' ? 'card card-oss' : 'card'); - cardDiv.className = cardClass; - - cardDiv.innerHTML = ` -
-

${tool.name}

-
- ${tool.isHosted ? 'Self-Hosted' : ''} - ${tool.license !== 'Proprietary' ? 'Open Source' : ''} -
-
- -

- ${tool.description} -

- -
-
- - - - - - - ${tool.platforms.join(', ')} - -
- -
- - - - - - ${tool.skillLevel} - -
- -
- - - - - - ${tool.license} - -
-
- -
- ${tool.tags.map((tag: string) => `${tag}`).join('')} -
- - - ${tool.isHosted ? 'Access Service' : 'Visit Website'} +// This replaces the createToolCard function in index.astro script section + +// This replaces the createToolCard function in index.astro script section + +// This replaces the createToolCard function in index.astro script section + +// 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; + + // Create button HTML based on hosting status + const hasValidProjectUrl = tool.projectUrl !== undefined && + tool.projectUrl !== null && + tool.projectUrl !== "" && + tool.projectUrl.trim() !== ""; + + let buttonHTML; + if (tool.isHosted && hasValidProjectUrl) { + // Two buttons for self-hosted tools with both URLs + buttonHTML = ` +
+ + Project Page - `; + + Access Service + +
+ `; + } else if (tool.isHosted) { + // Single button for self-hosted tools with only project URL + buttonHTML = ` + + Project Page + + `; + } else { + // Single button for non-hosted tools + buttonHTML = ` + + Visit Website + + `; + } + + cardDiv.innerHTML = ` +
+

${tool.name}

+
+ ${tool.isHosted ? 'Self-Hosted' : ''} + ${tool.license !== 'Proprietary' ? 'Open Source' : ''} +
+
+ +

+ ${tool.description} +

+ +
+
+ + + + + + + ${tool.platforms.join(', ')} + +
- return cardDiv; - } +
+ + + + + + ${tool.skillLevel} + +
+ +
+ + + + + + ${tool.license} + +
+
+ +
+ ${tool.tags.map(tag => `${tag}`).join('')} +
+ + ${buttonHTML} + `; + + return cardDiv; +} }); \ No newline at end of file diff --git a/src/styles/global.css b/src/styles/global.css index 6414003..264bae8 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -472,6 +472,15 @@ footer { flex-direction: column; text-align: center; } + /* Add this inside the existing @media (max-width: 768px) block */ + .collaboration-tools-compact { + flex-direction: column; + } + + .collaboration-tool-compact { + min-width: auto; + max-width: none; + } } /* Animations */ @@ -482,4 +491,64 @@ footer { .fade-in { animation: fadeIn 0.3s ease-in; +} + +/* Compact Collaboration Tools for Matrix View */ +.collaboration-tools-compact { + display: flex; + gap: 1rem; + flex-wrap: wrap; +} + +.collaboration-tool-compact { + background-color: var(--color-bg); + border: 1px solid var(--color-border); + border-radius: 0.375rem; + padding: 0.75rem; + min-width: 200px; + max-width: 300px; + flex: 1; + cursor: pointer; + transition: all 0.2s ease; +} + +.collaboration-tool-compact:hover { + border-color: var(--color-primary); + box-shadow: var(--shadow-sm); +} + +.collaboration-tool-compact.hosted { + background-color: var(--color-hosted-bg); + border-color: var(--color-hosted); +} + +.collaboration-tool-compact.oss { + background-color: var(--color-oss-bg); + border-color: var(--color-oss); +} + +.tool-compact-header { + display: flex; + justify-content: space-between; + align-items: start; + margin-bottom: 0.5rem; +} + +.badge-mini { + display: inline-flex; + align-items: center; + padding: 0.0625rem 0.375rem; + border-radius: 9999px; + font-size: 0.625rem; + font-weight: 500; +} + +.badge-mini.badge-primary { + background-color: var(--color-primary); + color: white; +} + +.badge-mini.badge-success { + background-color: var(--color-accent); + color: white; } \ No newline at end of file