Commit Graph

189 Commits

Author SHA1 Message Date
fuomag9
461df12ae8 fix search crash 2026-02-27 22:28:19 +01:00
fuomag9
a45a156068 fix pages viewing 2026-02-27 19:49:11 +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
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
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
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
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
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
fuomag9
75044c8d9b fix: harden security post-review (JWT exposure, rate limiter, token expiry, timing)
- Raw JWT never sent to browser: page.tsx uses peekLinkingToken (read-only),
  client sends opaque linkingId, API calls retrieveLinkingToken server-side
- link-account rate limiter now uses isRateLimited/registerFailedAttempt/
  resetAttempts correctly (count only failures, reset on success)
- linking_tokens gains expiresAt column (indexed) + opportunistic expiry
  purge on insert to prevent unbounded table growth
- secureTokenCompare fixed: pad+slice to expected length so timing is
  constant regardless of submitted token length (no length leak)
- autoLinkOAuth uses config.oauth.allowAutoLinking (boolean) instead of
  process.env truthy check that mishandles OAUTH_ALLOW_AUTO_LINKING=false
- Add Permissions-Policy header; restore X-Frame-Options for legacy UAs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 20:58:21 +01:00
fuomag9
b2238f3101 fix: gate unsafe-eval to dev, drop redundant X-Frame-Options, document PKCE+state
- CSP script-src 'unsafe-eval' is now dev-only; Next.js HMR needs it in
  development but the production standalone build does not
- Remove X-Frame-Options: DENY since frame-ancestors 'none' in CSP supersedes
  it in all modern browsers; keeping both creates a maintenance hazard
- Add comment explaining why state check is added alongside PKCE default

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 20:36:43 +01:00
fuomag9
b5b15c2496 fix: use explicit empty Buffer as HKDF salt and log legacy key fallback
- Replace empty string "" salt with Buffer.alloc(0) for explicit intent
  in security-critical HKDF call
- Add console.warn when legacy SHA-256 decryption path is taken so
  operators can track when all secrets have been re-encrypted

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 20:33:45 +01:00
fuomag9
48385684f9 fix: add PKCE to OAuth checks and HTTP security response headers
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 18:43:00 +01:00
fuomag9
a1c18cf09c fix: derive AES key with HKDF for key separation from JWT signing key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 18:42:46 +01:00
fuomag9
66ad3e9431 fix: enforce unique provider+subject constraint and harden sync route
- Change providerSubjectIdx from index to uniqueIndex in schema.ts to
  prevent multiple users sharing the same (provider, subject) pair,
  which caused non-deterministic sign-in resolution via findFirst.
- Add migration 0008_unique_provider_subject.sql: DROP the existing
  non-unique index and CREATE UNIQUE INDEX in its place.
- Validate INSTANCE_SYNC_MAX_BYTES env var in sync route: fall back to
  10 MB default when the value is non-numeric (e.g. 'off') or
  non-positive, preventing NaN comparisons that silently disabled the
  size limit.
- Return a generic error message to callers on applySyncPayload /
  applyCaddyConfig failure instead of leaking the raw error string;
  the original message is still stored internally via setSlaveLastSync.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 18:41:12 +01:00
fuomag9
618982484c fix: verify OAuth provider email against pending link to prevent account takeover
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 18:36:41 +01:00
fuomag9
9a189ea342 fix: store OAuth linking token server-side, remove JWT from URL and audit log
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 09:31:27 +01:00
fuomag9
0758e5b27a feat: support fail_closed option from caddy-blocker-plugin
New field from upstream plugin: when the real client IP is
indeterminate (trusted proxy present but no usable XFF entry),
fail_closed=true blocks the request instead of passing it through.

- Add fail_closed to GeoBlockSettings type
- Include in mergeGeoBlockSettings (OR semantics: either global or host enables it)
- Emit fail_closed in buildBlockerHandler (only when true)
- Parse geoblock_fail_closed from form in both settings and proxy-host actions
- Add Checkbox UI in the Advanced accordion of GeoBlockFields

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-25 09:14:46 +01:00
fuomag9
ccef82cca8 feat: add GeoIP status API route and improved geoblock UI 2026-02-25 01:22:04 +01:00
fuomag9
18c890bb21 feat: redesign GeoBlockFields UI with tabs, Autocomplete tag inputs, and accordion 2026-02-23 23:55:40 +01:00
fuomag9
9254d8e910 fix: use node:http for Caddy admin API calls to avoid Sec-Fetch-Mode CORS triggering 2026-02-23 23:49:05 +01:00
fuomag9
85af993c77 fix: add Origin header to Caddy admin API requests to satisfy CORS origin check 2026-02-23 22:27:31 +01:00
fuomag9
497e58db14 fix: include admin origins in generated Caddy config so they survive /load 2026-02-23 21:50:50 +01:00
fuomag9
b0abb407c6 feat: add GeoBlockFields to create and edit proxy host dialogs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:38 +01:00
fuomag9
7165dc4b05 fix: always render geoblock_mode hidden input regardless of showModeSelector
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:38 +01:00
fuomag9
821842b3a9 feat: add GeoBlockFields UI component
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:38 +01:00
fuomag9
fd9aa986d9 fix: correct enabled logic in geoblock merge and route injection 2026-02-23 19:56:37 +01:00
fuomag9
80177bf067 feat: inject blocker handler into proxy routes for geoblocking
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:37 +01:00
fuomag9
f54b7db96f fix: align GeoBlock hydrators with existing patterns in proxy host model
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:37 +01:00
fuomag9
e6e35646c0 feat: add GeoBlock types and hydration to proxy host model
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:37 +01:00
fuomag9
15208313a8 feat: add GeoBlockSettings type and helpers to settings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-23 19:56:37 +01:00
fuomag9
32f232ebee better UI for dns pinning 2026-02-22 10:00:52 +01:00
fuomag9
bb8a0d1023 implemented upstream pinning 2026-02-22 01:11:56 +01:00
fuomag9
7e4df5e50b removed redirect feature 2026-02-13 22:53:11 +01:00
fuomag9
eecacfb271 The static response feature has been completely removed 2026-02-09 01:15:28 +01:00
fuomag9
6d56cf2288 deprecate deadhosts, move it to the GUI as a custom response feature 2026-02-07 00:51:48 +01:00
fuomag9
90916bd709 various security fixes
Sync secrets encrypted at rest
Sync endpoint hardening
Avatar upload SVG restriction
2026-01-25 11:27:14 +01:00
fuomag9
6fb39dc809 Implement slave-master architecture 2026-01-25 01:39:36 +01:00
fuomag9
648d12bf16 The fix now properly merges the DNS resolver config into the existing transport, preserving TLS settings for HTTPS upstreams 2026-01-22 22:44:31 +01:00
fuomag9
7f93e9e784 Implement custom dns servers 2026-01-22 20:47:56 +01:00
fuomag9
49cf4f5ed1 added load balancing settings 2026-01-21 22:23:17 +01:00
fuomag9
d874cb9a69 add duplicate button and fix http protocol parsing in case user inputs protocol 2026-01-20 01:01:16 +01:00
fuomag9
85c7a0f8c7 finalized UI and website for 1.0 release 2026-01-15 01:16:25 +01:00
fuomag9
8ec483b14f fix some permission stuff 2026-01-04 18:49:24 +01:00