feat(18-01): chi v5 dependency, go:embed static assets, HTML layout and overview templates
- Add chi v5.2.5 to go.mod - Vendor htmx v2.0.4 minified JS in pkg/web/static/ - Create go:embed directives for static/ and templates/ - Create layout.html with nav bar and Tailwind CDN - Create overview.html with stat cards and findings table
This commit is contained in:
1
go.mod
1
go.mod
@@ -44,6 +44,7 @@ require (
|
|||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/emirpasic/gods v1.18.1 // indirect
|
github.com/emirpasic/gods v1.18.1 // indirect
|
||||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||||
|
github.com/go-chi/chi/v5 v5.2.5 // indirect
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||||
github.com/go-git/go-billy/v5 v5.8.0 // indirect
|
github.com/go-git/go-billy/v5 v5.8.0 // indirect
|
||||||
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
|
||||||
|
|||||||
6
go.sum
6
go.sum
@@ -53,6 +53,8 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S
|
|||||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||||
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU=
|
||||||
|
github.com/go-chi/chi/v5 v5.2.5 h1:Eg4myHZBjyvJmAFjFvWgrqDTXFyOzjj7YIm3L3mu6Ug=
|
||||||
|
github.com/go-chi/chi/v5 v5.2.5/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0=
|
||||||
github.com/go-co-op/gocron/v2 v2.19.1 h1:B4iLeA0NB/2iO3EKQ7NfKn5KsQgZfjb2fkvoZJU3yBI=
|
github.com/go-co-op/gocron/v2 v2.19.1 h1:B4iLeA0NB/2iO3EKQ7NfKn5KsQgZfjb2fkvoZJU3yBI=
|
||||||
github.com/go-co-op/gocron/v2 v2.19.1/go.mod h1:5lEiCKk1oVJV39Zg7/YG10OnaVrDAV5GGR6O0663k6U=
|
github.com/go-co-op/gocron/v2 v2.19.1/go.mod h1:5lEiCKk1oVJV39Zg7/YG10OnaVrDAV5GGR6O0663k6U=
|
||||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
|
||||||
@@ -189,10 +191,6 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavM
|
|||||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||||
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
|
||||||
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
|
||||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
|
||||||
go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU=
|
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
|
||||||
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
|
||||||
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
|
||||||
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y=
|
||||||
|
|||||||
14
pkg/web/embed.go
Normal file
14
pkg/web/embed.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package web
|
||||||
|
|
||||||
|
import "embed"
|
||||||
|
|
||||||
|
// staticFiles holds the vendored static assets (htmx.min.js, style.css, etc.)
|
||||||
|
// embedded at compile time.
|
||||||
|
//
|
||||||
|
//go:embed static/*
|
||||||
|
var staticFiles embed.FS
|
||||||
|
|
||||||
|
// templateFiles holds HTML templates embedded at compile time.
|
||||||
|
//
|
||||||
|
//go:embed templates/*
|
||||||
|
var templateFiles embed.FS
|
||||||
1
pkg/web/static/htmx.min.js
vendored
Normal file
1
pkg/web/static/htmx.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
39
pkg/web/static/style.css
Normal file
39
pkg/web/static/style.css
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* KeyHunter Dashboard — custom overrides (Tailwind CDN handles utility classes) */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont,
|
||||||
|
"Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stat card styling */
|
||||||
|
.stat-card {
|
||||||
|
border-radius: 0.5rem;
|
||||||
|
padding: 1.5rem;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Findings table */
|
||||||
|
.findings-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
.findings-table th,
|
||||||
|
.findings-table td {
|
||||||
|
padding: 0.75rem 1rem;
|
||||||
|
text-align: left;
|
||||||
|
border-bottom: 1px solid #e5e7eb;
|
||||||
|
}
|
||||||
|
.findings-table th {
|
||||||
|
font-weight: 600;
|
||||||
|
color: #374151;
|
||||||
|
background-color: #f9fafb;
|
||||||
|
}
|
||||||
|
.findings-table tr:hover {
|
||||||
|
background-color: #f3f4f6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation active link */
|
||||||
|
.nav-link-active {
|
||||||
|
border-bottom: 2px solid #3b82f6;
|
||||||
|
color: #3b82f6;
|
||||||
|
}
|
||||||
43
pkg/web/templates/layout.html
Normal file
43
pkg/web/templates/layout.html
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
{{define "layout"}}<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>{{if .PageTitle}}{{.PageTitle}} - {{end}}KeyHunter Dashboard</title>
|
||||||
|
<script src="https://cdn.tailwindcss.com"></script>
|
||||||
|
<script src="/static/htmx.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="/static/style.css">
|
||||||
|
</head>
|
||||||
|
<body class="bg-gray-50 min-h-screen">
|
||||||
|
<!-- Navigation -->
|
||||||
|
<nav class="bg-white shadow-sm border-b border-gray-200">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="flex justify-between h-16">
|
||||||
|
<div class="flex items-center space-x-8">
|
||||||
|
<a href="/" class="text-xl font-bold text-gray-900">KeyHunter</a>
|
||||||
|
<div class="hidden md:flex space-x-6">
|
||||||
|
<a href="/" class="text-gray-600 hover:text-gray-900 px-1 py-2 text-sm font-medium">Overview</a>
|
||||||
|
<a href="/keys" class="text-gray-600 hover:text-gray-900 px-1 py-2 text-sm font-medium">Keys</a>
|
||||||
|
<a href="/providers" class="text-gray-600 hover:text-gray-900 px-1 py-2 text-sm font-medium">Providers</a>
|
||||||
|
<a href="/recon" class="text-gray-600 hover:text-gray-900 px-1 py-2 text-sm font-medium">Recon</a>
|
||||||
|
<a href="/dorks" class="text-gray-600 hover:text-gray-900 px-1 py-2 text-sm font-medium">Dorks</a>
|
||||||
|
<a href="/settings" class="text-gray-600 hover:text-gray-900 px-1 py-2 text-sm font-medium">Settings</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<!-- Main content -->
|
||||||
|
<main class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
|
||||||
|
{{block "content" .}}{{end}}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<footer class="bg-white border-t border-gray-200 mt-auto">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
|
||||||
|
<p class="text-sm text-gray-500 text-center">KeyHunter - API Key Scanner</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>{{end}}
|
||||||
77
pkg/web/templates/overview.html
Normal file
77
pkg/web/templates/overview.html
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
{{template "layout" .}}
|
||||||
|
|
||||||
|
{{define "content"}}
|
||||||
|
<!-- Stat cards -->
|
||||||
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6 mb-8">
|
||||||
|
<div class="stat-card bg-white border border-gray-200">
|
||||||
|
<p class="text-sm font-medium text-gray-500">Total Keys Found</p>
|
||||||
|
<p class="mt-2 text-3xl font-bold text-gray-900">{{.TotalKeys}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card bg-white border border-gray-200">
|
||||||
|
<p class="text-sm font-medium text-gray-500">Providers Loaded</p>
|
||||||
|
<p class="mt-2 text-3xl font-bold text-gray-900">{{.TotalProviders}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card bg-white border border-gray-200">
|
||||||
|
<p class="text-sm font-medium text-gray-500">Recon Sources</p>
|
||||||
|
<p class="mt-2 text-3xl font-bold text-gray-900">{{.ReconSources}}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card bg-white border border-gray-200">
|
||||||
|
<p class="text-sm font-medium text-gray-500">Last Scan</p>
|
||||||
|
<p class="mt-2 text-xl font-bold text-gray-900">{{if .LastScan}}{{.LastScan}}{{else}}Never{{end}}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Recent findings -->
|
||||||
|
<div class="bg-white shadow-sm rounded-lg border border-gray-200">
|
||||||
|
<div class="px-6 py-4 border-b border-gray-200">
|
||||||
|
<h2 class="text-lg font-semibold text-gray-900">Recent Findings</h2>
|
||||||
|
</div>
|
||||||
|
{{if .RecentFindings}}
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="findings-table">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Provider</th>
|
||||||
|
<th>Masked Key</th>
|
||||||
|
<th>Source</th>
|
||||||
|
<th>Confidence</th>
|
||||||
|
<th>Verified</th>
|
||||||
|
<th>Date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{{range .RecentFindings}}
|
||||||
|
<tr>
|
||||||
|
<td class="font-medium">{{.ProviderName}}</td>
|
||||||
|
<td class="font-mono text-sm text-gray-600">{{.KeyMasked}}</td>
|
||||||
|
<td class="text-sm text-gray-600">{{.SourcePath}}</td>
|
||||||
|
<td>
|
||||||
|
{{if eq .Confidence "high"}}
|
||||||
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">High</span>
|
||||||
|
{{else if eq .Confidence "medium"}}
|
||||||
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-yellow-100 text-yellow-800">Medium</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-100 text-gray-800">{{.Confidence}}</span>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{if .Verified}}
|
||||||
|
<span class="text-green-600 font-medium">Live</span>
|
||||||
|
{{else}}
|
||||||
|
<span class="text-gray-400">-</span>
|
||||||
|
{{end}}
|
||||||
|
</td>
|
||||||
|
<td class="text-sm text-gray-500">{{.CreatedAt.Format "2006-01-02 15:04"}}</td>
|
||||||
|
</tr>
|
||||||
|
{{end}}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="px-6 py-12 text-center text-gray-500">
|
||||||
|
<p class="text-lg">No findings yet</p>
|
||||||
|
<p class="mt-1 text-sm">Run a scan to detect API keys</p>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
Reference in New Issue
Block a user