mirror of
https://github.com/hhftechnology/vps-monitor.git
synced 2026-04-28 03:29:55 +00:00
Introduce a full scanner subsystem (vulnerability scanning and SBOM generation) across frontend, backend, and mobile. Frontend: - Add scanner UI components: ScanDialog, BulkScanDialog, SBOMDialog, ScanResultsTable, ScanResultsSummary, ScanResultsExport and hooks/use-scan-query. - Add API clients for scan operations (start-scan, start-bulk-scan, get-scan-jobs, get-scan-results, generate-sbom, scanner-config). - Integrate scan/SBOM controls into ImagesTable (scan per-image, bulk scan, SBOM generation, download/export). - Update settings UI to surface scanner configuration. Backend (home service): - Add scanner models, handlers and scanner implementations (Grype/Trivy), notifier, SBOM support, and persistent store scaffolding for scan jobs/results. - Add scan-related API handlers and wire routes into router.go and handlers.go; adjust main.go and config/manager to support scanner settings. - Tests updated for auth service where required. Mobile: - Add scanner feature support (API, hooks, components, types, utils) and a Settings page entry. Why: Enable users to run vulnerability scans (single and bulk), monitor job progress, retrieve and export scan results, and generate/download SBOMs for container images.
107 lines
2.9 KiB
TypeScript
107 lines
2.9 KiB
TypeScript
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
|
|
import { startScan, type StartScanParams } from "../api/start-scan";
|
|
import { startBulkScan, type StartBulkScanParams } from "../api/start-bulk-scan";
|
|
import { getScanJob, cancelScanJob } from "../api/get-scan-jobs";
|
|
import { getScanResults } from "../api/get-scan-results";
|
|
import { generateSBOM, getSBOMJob, type GenerateSBOMParams } from "../api/generate-sbom";
|
|
import {
|
|
getScannerConfig,
|
|
updateScannerConfig,
|
|
testScanNotification,
|
|
} from "../api/scanner-config";
|
|
import type { ScannerConfig } from "../types";
|
|
|
|
const SCANNER_CONFIG_KEY = ["scannerConfig"] as const;
|
|
|
|
export function useScannerConfig() {
|
|
return useQuery({
|
|
queryKey: SCANNER_CONFIG_KEY,
|
|
queryFn: getScannerConfig,
|
|
staleTime: 30_000,
|
|
});
|
|
}
|
|
|
|
export function useUpdateScannerConfig() {
|
|
const queryClient = useQueryClient();
|
|
return useMutation({
|
|
mutationFn: (config: ScannerConfig) => updateScannerConfig(config),
|
|
onSuccess: () => {
|
|
queryClient.invalidateQueries({ queryKey: SCANNER_CONFIG_KEY });
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useTestScanNotification() {
|
|
return useMutation({
|
|
mutationFn: () => testScanNotification(),
|
|
});
|
|
}
|
|
|
|
export function useStartScan() {
|
|
return useMutation({
|
|
mutationFn: (params: StartScanParams) => startScan(params),
|
|
});
|
|
}
|
|
|
|
export function useStartBulkScan() {
|
|
return useMutation({
|
|
mutationFn: (params: StartBulkScanParams) => startBulkScan(params),
|
|
});
|
|
}
|
|
|
|
export function useScanJob(id: string | null, enabled = true) {
|
|
return useQuery({
|
|
queryKey: ["scanJob", id],
|
|
queryFn: () => getScanJob(id!),
|
|
enabled: enabled && !!id,
|
|
refetchInterval: (query) => {
|
|
const data = query.state.data;
|
|
if (!data) return 2000;
|
|
const job = data.job || data.bulkJob;
|
|
if (!job) return false;
|
|
const status = job.status;
|
|
if (status === "complete" || status === "failed" || status === "cancelled") {
|
|
return false;
|
|
}
|
|
return 2000;
|
|
},
|
|
});
|
|
}
|
|
|
|
export function useCancelScan() {
|
|
return useMutation({
|
|
mutationFn: (id: string) => cancelScanJob(id),
|
|
});
|
|
}
|
|
|
|
export function useScanResults(imageRef: string, host: string, enabled = true) {
|
|
return useQuery({
|
|
queryKey: ["scanResults", imageRef, host],
|
|
queryFn: () => getScanResults(imageRef, host),
|
|
enabled,
|
|
staleTime: 30_000,
|
|
});
|
|
}
|
|
|
|
export function useGenerateSBOM() {
|
|
return useMutation({
|
|
mutationFn: (params: GenerateSBOMParams) => generateSBOM(params),
|
|
});
|
|
}
|
|
|
|
export function useSBOMJob(id: string | null, enabled = true) {
|
|
return useQuery({
|
|
queryKey: ["sbomJob", id],
|
|
queryFn: () => getSBOMJob(id!),
|
|
enabled: enabled && !!id,
|
|
refetchInterval: (query) => {
|
|
const data = query.state.data;
|
|
if (!data) return 2000;
|
|
if (data.status === "complete" || data.status === "failed" || data.status === "cancelled") {
|
|
return false;
|
|
}
|
|
return 2000;
|
|
},
|
|
});
|
|
}
|