mirror of
https://github.com/Dvorinka/Dash.git
synced 2026-10-29 08:04:58 +00:00
feat: domain monitoring (merge plan M2, phase 1)
Port of the domain-intelligence pipeline from the old Beszel fork, adapted to Dash's SQLite + no-PocketBase architecture: - internal/domain: RDAP via IANA bootstrap (cached), TCP WHOIS :43 fallback with multi-format parser, DNS (NS/MX/TXT/CNAME/A/AAAA), TLS leaf cert details, ip-api.com geolocation, provider detection (DNS/email/hosting/CA). HTML scraping, paid APIs, and exec-based whois deliberately dropped. - API: domains CRUD + synchronous refresh + domain_checks snapshot history; refresh runs inside the monitor sweep on interval_h. - UI: /domains + /domains/:id pages, add/edit dialog, domain board widget (favicon + expiry countdown), palette + nav entries, domainId picker in the widget dialog. - Test seam: Server.lookup injects the refresh; domain tests run hermetic against a stubbed result. Verified live: github.com resolves MarkMonitor expiry 2028-10, Route 53 DNS, GitHub Pages hosting, Sectigo cert with 69d left. Authored By: TDvorak <[email protected]> Generated with Devin (https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
1ff1b29ae7
commit
f9fd1d9cf2
18 files changed
+2376
-14
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { Link, Route, useLocation } from "wouter";
|
||||
import { Activity, LayoutGrid, Moon, Plus, Search, Settings, Sun } from "lucide-react";
|
||||
import { Activity, Globe, LayoutGrid, Moon, Plus, Search, Settings, Sun } from "lucide-react";
|
||||
import { BoardProvider, useBoard } from "@/board/store";
|
||||
import { Board } from "@/board/Board";
|
||||
import { ServiceDialog } from "@/components/ServiceDialog";
|
||||
@@ -9,6 +9,8 @@ import { SettingsDialog } from "@/components/SettingsDialog";
|
||||
import { CommandPalette } from "@/components/CommandPalette";
|
||||
import { MonitorsPage } from "@/pages/MonitorsPage";
|
||||
import { MonitorDetailPage } from "@/pages/MonitorDetailPage";
|
||||
import { DomainsPage } from "@/pages/DomainsPage";
|
||||
import { DomainDetailPage } from "@/pages/DomainDetailPage";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import type { Item } from "@/types";
|
||||
@@ -24,6 +26,7 @@ export default function App() {
|
||||
const NAV = [
|
||||
{ href: "/", label: "Board", icon: LayoutGrid },
|
||||
{ href: "/monitors", label: "Monitors", icon: Activity },
|
||||
{ href: "/domains", label: "Domains", icon: Globe },
|
||||
];
|
||||
|
||||
function Shell() {
|
||||
@@ -132,6 +135,12 @@ function Shell() {
|
||||
<Route path="/monitors/:id">
|
||||
{(p) => <MonitorDetailPage id={p.id} />}
|
||||
</Route>
|
||||
<Route path="/domains">
|
||||
<DomainsPage />
|
||||
</Route>
|
||||
<Route path="/domains/:id">
|
||||
{(p) => <DomainDetailPage id={p.id} />}
|
||||
</Route>
|
||||
|
||||
<ServiceDialog open={svcOpen} onOpenChange={setSvcOpen} item={editing?.kind === "service" ? editing : undefined} />
|
||||
<WidgetDialog open={wdgOpen} onOpenChange={setWdgOpen} item={editing?.kind === "widget" ? editing : undefined} />
|
||||
|
||||
Reference in new issue
Block a user