feat: add Deep Scan toggle to scan dialog
Collapsible Deep Scan section in ScanConfigModal exposes extra port ranges, HTTP probe and TLS-verify switches. Pre-filled from saved defaults; edits are passed to trigger() as a per-scan override and do not change the persisted defaults (those live in the Options/scan config). scanApi.trigger now accepts an optional deep-scan body. ha-relevant: yes
This commit is contained in:
@@ -1,10 +1,10 @@
|
||||
import { useState, useEffect } from 'react'
|
||||
import { Plus, Trash2, Settings } from 'lucide-react'
|
||||
import { Plus, Trash2, Settings, ChevronRight, ChevronDown } from 'lucide-react'
|
||||
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogFooter } from '@/components/ui/dialog'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { scanApi } from '@/api/client'
|
||||
import { scanApi, type DeepScanConfig } from '@/api/client'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
interface ScanConfigModalProps {
|
||||
@@ -13,24 +13,56 @@ interface ScanConfigModalProps {
|
||||
onScanNow: () => void
|
||||
}
|
||||
|
||||
const DEEP_DEFAULTS: DeepScanConfig = { http_ranges: [], http_probe_enabled: false, verify_tls: false }
|
||||
|
||||
export function ScanConfigModal({ open, onClose, onScanNow }: ScanConfigModalProps) {
|
||||
const [ranges, setRanges] = useState<string[]>([''])
|
||||
const [saving, setSaving] = useState(false)
|
||||
|
||||
// Deep-scan section. Pre-filled from persisted defaults; edits here are a
|
||||
// per-scan override passed to trigger() — they do NOT change the saved defaults.
|
||||
const [deepOpen, setDeepOpen] = useState(false)
|
||||
const [deepDefaults, setDeepDefaults] = useState<DeepScanConfig>(DEEP_DEFAULTS)
|
||||
const [httpProbe, setHttpProbe] = useState(false)
|
||||
const [verifyTls, setVerifyTls] = useState(false)
|
||||
const [httpRangesText, setHttpRangesText] = useState('')
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return
|
||||
scanApi.getConfig()
|
||||
.then((res) => setRanges(res.data.ranges.length > 0 ? res.data.ranges : ['']))
|
||||
.then((res) => {
|
||||
const d = res.data
|
||||
setRanges(d.ranges.length > 0 ? d.ranges : [''])
|
||||
const deep: DeepScanConfig = {
|
||||
http_ranges: d.http_ranges ?? [],
|
||||
http_probe_enabled: d.http_probe_enabled ?? false,
|
||||
verify_tls: d.verify_tls ?? false,
|
||||
}
|
||||
setDeepDefaults(deep)
|
||||
setHttpProbe(deep.http_probe_enabled)
|
||||
setVerifyTls(deep.verify_tls)
|
||||
setHttpRangesText(deep.http_ranges.join(', '))
|
||||
setDeepOpen(deep.http_probe_enabled || deep.http_ranges.length > 0)
|
||||
})
|
||||
.catch(() => {/* use defaults */})
|
||||
}, [open])
|
||||
|
||||
const parseHttpRanges = () =>
|
||||
httpRangesText.split(',').map((r) => r.trim()).filter(Boolean)
|
||||
|
||||
const handleScanNow = async () => {
|
||||
const cleaned = ranges.map((r) => r.trim()).filter(Boolean)
|
||||
if (cleaned.length === 0) { toast.error('Add at least one IP range'); return }
|
||||
setSaving(true)
|
||||
try {
|
||||
await scanApi.saveConfig({ ranges: cleaned })
|
||||
await scanApi.trigger()
|
||||
// Persist IP ranges; leave deep-scan defaults as configured in Options.
|
||||
await scanApi.saveConfig({ ranges: cleaned, ...deepDefaults })
|
||||
// Per-scan deep-scan override from this dialog.
|
||||
await scanApi.trigger({
|
||||
http_ranges: parseHttpRanges(),
|
||||
http_probe_enabled: httpProbe,
|
||||
verify_tls: verifyTls,
|
||||
})
|
||||
onScanNow()
|
||||
onClose()
|
||||
} catch {
|
||||
@@ -84,6 +116,57 @@ export function ScanConfigModal({ open, onClose, onScanNow }: ScanConfigModalPro
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Deep Scan (opt-in) */}
|
||||
<div className="space-y-2 border-t border-border pt-3">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setDeepOpen((v) => !v)}
|
||||
className="flex items-center gap-1.5 text-sm text-muted-foreground hover:text-foreground"
|
||||
>
|
||||
{deepOpen ? <ChevronDown size={14} /> : <ChevronRight size={14} />}
|
||||
Deep Scan
|
||||
</button>
|
||||
|
||||
{deepOpen && (
|
||||
<div className="space-y-3 pl-1">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
Scan extra ports and probe HTTP services to identify apps on custom ports.
|
||||
Overrides the saved defaults for this scan only.
|
||||
</p>
|
||||
|
||||
<div className="space-y-1.5">
|
||||
<Label className="text-xs text-muted-foreground">Extra port ranges</Label>
|
||||
<Input
|
||||
value={httpRangesText}
|
||||
onChange={(e) => setHttpRangesText(e.target.value)}
|
||||
placeholder="8000-8100, 9000-9100"
|
||||
className="font-mono text-sm bg-[#0d1117] border-border"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label className="flex items-center gap-2 text-sm text-foreground cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={httpProbe}
|
||||
onChange={(e) => setHttpProbe(e.target.checked)}
|
||||
className="accent-[#00d4ff]"
|
||||
/>
|
||||
Enable HTTP probe
|
||||
</label>
|
||||
|
||||
<label className="flex items-center gap-2 text-sm text-foreground cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={verifyTls}
|
||||
onChange={(e) => setVerifyTls(e.target.checked)}
|
||||
className="accent-[#00d4ff]"
|
||||
/>
|
||||
Verify TLS certificates
|
||||
</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-muted-foreground flex items-center gap-1.5">
|
||||
<Settings size={11} />
|
||||
Status check interval can be configured in the sidebar Settings.
|
||||
|
||||
Reference in New Issue
Block a user