Files
wild-central/web/src/hooks/useCrowdSec.ts
Paul Payne 735f3fcb05 feat: Add Wild Central web app (Central-only UI)
Extract Central pages from the wild-cloud web app into a standalone
React app for Wild Central. Includes:

- Central overview, DNS, DHCP, Firewall, VPN, Ingress, CrowdSec pages
- Simplified sidebar with Central-only navigation
- Branding updated to "Wild Central"
- All Cloud-specific pages, components, hooks, and API services removed
- TypeScript type-check and production build pass

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-07-09 04:10:43 +00:00

129 lines
4.1 KiB
TypeScript

import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { crowdSecApi, type AddDecisionRequest } from '../services/api/networking';
export const useCrowdSec = () => {
const queryClient = useQueryClient();
const statusQuery = useQuery({
queryKey: ['crowdsec', 'status'],
queryFn: () => crowdSecApi.getStatus(),
refetchInterval: false,
staleTime: 30000,
});
const summaryQuery = useQuery({
queryKey: ['crowdsec', 'summary'],
queryFn: () => crowdSecApi.getSummary(),
refetchInterval: false,
staleTime: 300000, // 5 minutes — CAPI bans change slowly
enabled: statusQuery.data?.active ?? false,
});
const alertsQuery = useQuery({
queryKey: ['crowdsec', 'alerts'],
queryFn: () => crowdSecApi.getAlerts(50),
refetchInterval: false,
staleTime: 60000,
enabled: statusQuery.data?.active ?? false,
});
const alertsGraphQuery = useQuery({
queryKey: ['crowdsec', 'alerts-graph'],
queryFn: () => crowdSecApi.getAlerts(500),
refetchInterval: false,
staleTime: 120000,
enabled: statusQuery.data?.active ?? false,
});
const decisionsQuery = useQuery({
queryKey: ['crowdsec', 'decisions'],
queryFn: () => crowdSecApi.getDecisions(),
refetchInterval: false,
staleTime: 30000,
enabled: statusQuery.data?.active ?? false,
});
const addDecisionMutation = useMutation({
mutationFn: (req: AddDecisionRequest) => crowdSecApi.addDecision(req),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'decisions'] });
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'summary'] });
},
});
const deleteDecisionMutation = useMutation({
mutationFn: (id: number) => crowdSecApi.deleteDecision(id),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'decisions'] });
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'summary'] });
},
});
const deleteDecisionByIPMutation = useMutation({
mutationFn: (ip: string) => crowdSecApi.deleteDecisionByIP(ip),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'decisions'] });
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'summary'] });
},
});
const deleteBouncerMutation = useMutation({
mutationFn: (name: string) => crowdSecApi.deleteBouncer(name),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'status'] });
},
});
const deleteMachineMutation = useMutation({
mutationFn: (name: string) => crowdSecApi.deleteMachine(name),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'status'] });
},
});
const provisionMutation = useMutation({
mutationFn: (instanceName: string) => crowdSecApi.provision(instanceName),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['crowdsec', 'status'] });
},
});
return {
status: statusQuery.data,
isLoadingStatus: statusQuery.isLoading,
statusError: statusQuery.error,
summary: summaryQuery.data,
isLoadingSummary: summaryQuery.isLoading,
alerts: alertsQuery.data?.alerts ?? [],
isLoadingAlerts: alertsQuery.isLoading,
refetchAlerts: alertsQuery.refetch,
graphAlerts: alertsGraphQuery.data?.alerts ?? [],
isLoadingGraphAlerts: alertsGraphQuery.isLoading,
decisions: decisionsQuery.data?.decisions ?? [],
isLoadingDecisions: decisionsQuery.isLoading,
addDecision: addDecisionMutation.mutate,
isAddingDecision: addDecisionMutation.isPending,
addDecisionError: addDecisionMutation.error,
deleteDecision: deleteDecisionMutation.mutate,
isDeletingDecision: deleteDecisionMutation.isPending,
deleteDecisionByIP: deleteDecisionByIPMutation.mutate,
isDeletingByIP: deleteDecisionByIPMutation.isPending,
deleteBouncer: deleteBouncerMutation.mutate,
isDeletingBouncer: deleteBouncerMutation.isPending,
deleteMachine: deleteMachineMutation.mutate,
isDeletingMachine: deleteMachineMutation.isPending,
provision: provisionMutation.mutate,
isProvisioning: provisionMutation.isPending,
};
};