2248 Commits

Author SHA1 Message Date
fuomag9
494535d767 fixed website rendering chars 2026-02-27 22:34:35 +01:00
fuomag9
461df12ae8 fix search crash 2026-02-27 22:28:19 +01:00
fuomag9
6ac8fa5664 remove unneeded screenshots from readme 2026-02-27 22:27:03 +01:00
fuomag9
26e4a7c6f3 updated website 2026-02-27 21:58:04 +01:00
fuomag9
d7f0738bf0 update website 2026-02-27 21:32:36 +01:00
fuomag9
336c899b1e updated screenshots 2026-02-27 21:07:08 +01:00
fuomag9
000607cee7 updated documentation 2026-02-27 20:10:54 +01:00
fuomag9
fb561f7433 update dependencies 2026-02-27 19:53:01 +01:00
fuomag9
a45a156068 fix pages viewing 2026-02-27 19:49:11 +01:00
fuomag9
3d88f565ca fix: await searchParams Promise in all paginated pages (Next.js 15+) 2026-02-27 18:40:56 +01:00
fuomag9
f64eb2c8d0 fix: sync search state on navigation; move pagination before create form in access-lists
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 18:05:15 +01:00
fuomag9
f7a092f1e4 feat: add pagination to certificates ACME table
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 18:01:27 +01:00
fuomag9
5126273101 feat: add server-side pagination to access-lists page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 18:00:36 +01:00
fuomag9
6bd7fe92d8 feat: add server-side pagination to proxy-hosts page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 18:00:26 +01:00
fuomag9
ce042d968d feat: add server-side pagination and search to audit-log page 2026-02-27 18:00:23 +01:00
fuomag9
8bf07011f9 feat: add paginated list functions to DB models
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 17:58:23 +01:00
fuomag9
8555de7b9d fix: use numeric timestamp comparison for cert expiry; extract PaginationBar to avoid unconditional useSearchParams subscription
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 17:56:23 +01:00
fuomag9
89c5d4b838 feat: add pagination support to DataTable component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 17:53:23 +01:00
fuomag9
28f9fc1d8a feat: show ACME cert expiry and issuer in certificates page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 17:51:14 +01:00
fuomag9
97ba5547f1 feat: add ACME cert scanner utility
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 17:48:55 +01:00
fuomag9
27a7e6dab9 chore: mount caddy-data read-only to web container for cert scanning
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 17:48:54 +01:00
fuomag9
f9fba6963b docs: add implementation plan for ACME cert info and sitewide pagination 2026-02-27 17:44:26 +01:00
fuomag9
296d17205f fix: count ACME-issued certs in overview (not just imported ones)
Previously only counted rows in the certificates table (0 for most setups).
Now counts: proxy hosts with certificate_id=NULL (each gets one Caddy ACME cert
via HTTP-01/DNS-01) + imported certs with actual PEM data.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 16:19:24 +01:00
fuomag9
7e5626f328 fix: align nav icons with overview card icons
SwapHorizIcon→Proxy Hosts, VpnKeyIcon→Access Lists, SecurityIcon→Certificates,
HistoryIcon→Audit Log. Nav now uses the exact same icons as the overview stat
cards so identical sections share identical icons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 16:03:26 +01:00
fuomag9
3a6a5297d6 fix: replace thin/outlined nav icons with solid filled equivalents
DnsIcon→RouterIcon, SecurityIcon→LockIcon, ShieldIcon→WorkspacePremiumIcon,
HistoryIcon→AssignmentIcon — all now match the visual weight of Dashboard,
BarChart, and Settings icons.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 15:31:19 +01:00
fuomag9
2096ebf1ed fix: replace Outlined icon variants with filled equivalents for visual consistency
Replace DeleteOutline→Delete, CheckCircleOutline→CheckCircle, ErrorOutline→Error,
RemoveCircleOutline→RemoveCircle, InfoOutlined→Info across all dashboard components.
Replace custom SVG bar chart in OverviewClient with BarChartIcon.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 15:25:19 +01:00
fuomag9
bfb6b2060f fix: restore full-width nav list with rounded corners (borderRadius: 3)
Revert 2-column squircle grid back to original list layout —
same space usage as before, just with squircle-style border radius
on each ListItemButton instead of sharp rectangle edges.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 14:43:31 +01:00
fuomag9
155845f7ed fix: distribute nav squircles evenly across full sidebar height
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 14:39:41 +01:00
fuomag9
86172b38ed feat: redesign nav as 2-column squircle icon tiles
Replace full-width ListItemButton rows with a 2-column grid of
square tiles (borderRadius: 22%, aspectRatio: 1) containing a
centred icon and small label. Active tile uses primary.main fill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 14:33:32 +01:00
fuomag9
0955084772 fix: swap Proxy Hosts and Analytics nav order
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 14:27:05 +01:00
fuomag9
c8bc1f7500 fix: fixed-width host picker to prevent layout shift on long names
Replace minWidth/maxWidth with a fixed width:260 + flexShrink:0 so the
Autocomplete never resizes the header row. Chip labels also truncate
with ellipsis instead of wrapping.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 13:32:59 +01:00
fuomag9
1028322645 fix: collapse selected host chips to count badge when >2 selected
renderTags now shows individual chips for 1-2 selections, and a single
'N hosts' chip (with clear-all × button) for 3+. Prevents the input
from growing vertically when many hosts are selected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 12:13:08 +01:00
fuomag9
50028581b0 feat: add Select All/Clear buttons to host picker, fix popup overscroll
- PaperComponent header with "Select all" / "Clear" buttons; onMouseDown
  preventDefault keeps the popup open when clicking them
- ListboxProps overscrollBehavior: contain prevents the dropdown list's
  scroll from propagating to the page when reaching top/bottom

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:52:38 +01:00
fuomag9
e75018d686 fix: exclude IP address hosts from analytics host list
Only show configured domain names, not raw IPs (e.g. 127.0.0.1:80,
46.225.8.152) that appear in traffic events from direct access.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:47:03 +01:00
fuomag9
cf74451e9a feat: MUI date-time pickers, multiselect hosts with search, fix host list
- Replace native datetime-local inputs with @mui/x-date-pickers DateTimePicker
  (proper dark-themed calendar popover with time picker, DD/MM/YYYY HH:mm format,
  min/max constraints between pickers, 24h clock)
- Replace single-host Select with Autocomplete (multiple, disableCloseOnSelect):
  checkbox per option, chip display with limitTags=2, built-in search/filter
- getAnalyticsHosts() now unions traffic event hosts WITH all configured proxy host
  domains (parsed from proxyHosts.domains JSON), so every proxy appears in the list
- analytics-db: buildWhere accepts hosts: string[] (empty = all); uses inArray for
  multi-host filtering via drizzle-orm
- All 6 API routes updated: accept hosts param (comma-separated) instead of host

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 11:42:54 +01:00
fuomag9
9e2007eb0c feat: add custom date range picker, fix country click highlight on map
- Analytics default interval changed to 1h
- Add 'Custom' toggle option with datetime-local pickers (pre-filled to last 24h)
- Refactor analytics-db: buildWhere now takes from/to unix timestamps instead of Interval
- Export INTERVAL_SECONDS from analytics-db for route reuse
- All 6 API routes accept from/to params (fallback to interval if absent)
- Timeline bucket size computed from duration rather than hardcoded per interval
- Fix map country click highlight: bake isSelected into GeoJSON features (data-driven)
  instead of relying on Layer filter prop updates (unreliable in react-map-gl v8)
- Split highlight into countries-selected (data-driven) and countries-hover (filter-driven)
- Show tooltip at country centroid when selected via table, hover takes precedence

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 10:38:02 +01:00
fuomag9
608fb9c6fe fix: detect blocked requests via caddy-blocker log entries, add country click→map highlight 2026-02-27 09:22:06 +01:00
fuomag9
7553fe0bb5 fix: make world map fill available card height instead of fixed 340px 2026-02-27 02:00:00 +01:00
fuomag9
be2416d7b3 fix: normalize topojson numeric IDs to strip leading zeros for N2A lookup 2026-02-27 01:48:28 +01:00
fuomag9
1b5c392632 fix: switch to 50m topojson for sharper borders, show tooltip for all territories 2026-02-27 01:43:47 +01:00
fuomag9
a56e7ae83f fix: unwrap polygon rings to fix antimeridian artifacts for Fiji, Russia, etc 2026-02-27 01:37:00 +01:00
fuomag9
c84a9f9ce9 fix: cut antimeridian for GeoJSON to fix Russia polygon artifact 2026-02-27 01:29:36 +01:00
fuomag9
d60010227e fix: proper MapLibre choropleth with Popup, filter highlight, 1h/12h intervals
- Use Popup component for map-anchored tooltips (moves with lat/lng)
- Use filter+highlight layer for hover instead of feature state
- fitBounds to [-168,-56,168,74] to trim polar dead zones
- Country no-data color #1e293b vs ocean #0a1628 — clear contrast
- Visible borders rgba(148,163,184,0.18)
- Add 1h and 12h interval buttons to analytics UI
- formatTs handles 1h/12h with time-only format

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 01:08:55 +01:00
fuomag9
3dce8f7a01 fix: use mercator projection (naturalEarth unsupported in MapLibre), zoom 0 for full world view
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 00:48:26 +01:00
fuomag9
69f222e51f feat: migrate world map to react-map-gl/maplibre with Natural Earth projection
- Replace D3/SVG choropleth with react-map-gl MapGL component
- Use Natural Earth projection for proper world view
- Embed traffic data (norm, total, blocked, alpha2) as GeoJSON properties
- Use feature state only for hover highlighting
- Add 1h and 12h interval options to analytics
- Add worker-src blob: to CSP for MapLibre web workers

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 00:43:01 +01:00
fuomag9
3569bece53 fix: redesign world map with interactivity and proper visuals
- Dark ocean background (#0b1628) with country borders
- Three-stop color gradient (dark blue → blue → sky) with power curve
  distribution so low-traffic countries are still visible
- Hover highlights country in sky-300 with smooth CSS transition
- Floating tooltip on hover: flag emoji, country name, requests, blocked
- Color legend (Low → High) below the map
- Country names lookup table for all ~180 countries

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 21:49:27 +01:00
fuomag9
89a6a71d3e fix: serve world-atlas topojson locally to satisfy CSP connect-src
Fetching from cdn.jsdelivr.net was blocked by connect-src 'self'.
Copy countries-110m.json from world-atlas npm package into public/geo/
and reference it as /geo/countries-110m.json instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 21:38:01 +01:00
fuomag9
8be69d2774 feat: add analytics dashboard with traffic monitoring
- Parse Caddy access logs every 30s into traffic_events SQLite table
- GeoIP country lookup via maxmind (GeoLite2-Country.mmdb)
- 90-day retention with automatic purge
- Analytics page with interval (24h/7d/30d) and per-host filtering:
  - Stats cards: total requests, unique IPs, blocked count, block rate
  - Requests-over-time area chart (ApexCharts)
  - SVG world choropleth map (d3-geo + topojson-client, React 19 compatible)
  - Top countries table with flag emojis
  - HTTP protocol donut chart
  - Top user agents horizontal bar chart
  - Recent blocked requests table with pagination
- Traffic (24h) summary card on Overview page linking to analytics
- 7 authenticated API routes under /api/analytics/
- Share caddy-logs volume with web container (read-only)
- group_add caddy GID to web container for log file read access

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 20:43:23 +01:00
fuomag9
674e06e3c9 feat: replace country/continent TagInputs with visual flag pickers
Countries:
- Searchable chip grid (flag emoji + name + code) with 249 countries
- Instant search by name or ISO code prefix
- Select matching / Clear matching when search is active
- Select all / Clear all when no search
- Selected-count indicator in toolbar
- Summary strip showing all selected when search is active
- Custom thin scrollbar, 220px viewport

Continents:
- 7 clickable tiles with emoji + name + code
- Select all / Clear all toolbar
- Warning/success color theming per block/allow tab

Both pickers:
- accentColor prop (warning=orange for block, success=green for allow)
- Hidden form input for server compatibility
- Smooth 120ms transitions

Also simplified TagInput to a plain TextField with inline chips
(removes Autocomplete dependency for freeform fields like ASNs/CIDRs/IPs)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 01:31:12 +01:00
fuomag9
3442beba19 fix: expand private_ranges to CIDRs before passing to caddy-blocker-plugin
The blocker plugin only accepts literal IP/CIDR strings; Caddy's built-in
'private_ranges' shorthand is not understood by third-party modules.
Expand it to the equivalent CIDR list at config-build time.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 01:25:08 +01:00