Add DNS filtering with dnsmasq address=/ directives for wildcard blocking
Adds Pi-hole-style DNS filtering using dnsmasq's native address=/ directives, which block domains and all subdomains. Users subscribe to blocklists by URL or upload files, with suggested lists from Hagezi, Steven Black, and OISD. Background runner refreshes lists on a configurable interval (default 24h).
This commit is contained in:
101
web/src/hooks/useDnsFilter.ts
Normal file
101
web/src/hooks/useDnsFilter.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { dnsFilterApi, type CustomEntry } from '../services/api/dnsfilter';
|
||||
|
||||
export function useDnsFilter() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const statusQuery = useQuery({
|
||||
queryKey: ['dns-filter', 'status'],
|
||||
queryFn: () => dnsFilterApi.getStatus(),
|
||||
});
|
||||
|
||||
const configQuery = useQuery({
|
||||
queryKey: ['dns-filter', 'config'],
|
||||
queryFn: () => dnsFilterApi.getConfig(),
|
||||
});
|
||||
|
||||
const listsQuery = useQuery({
|
||||
queryKey: ['dns-filter', 'lists'],
|
||||
queryFn: () => dnsFilterApi.getLists(),
|
||||
});
|
||||
|
||||
const customQuery = useQuery({
|
||||
queryKey: ['dns-filter', 'custom'],
|
||||
queryFn: () => dnsFilterApi.getCustomEntries(),
|
||||
});
|
||||
|
||||
const suggestedQuery = useQuery({
|
||||
queryKey: ['dns-filter', 'suggested'],
|
||||
queryFn: () => dnsFilterApi.getSuggested(),
|
||||
staleTime: Infinity,
|
||||
});
|
||||
|
||||
const invalidateAll = () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['dns-filter'] });
|
||||
};
|
||||
|
||||
const updateConfigMutation = useMutation({
|
||||
mutationFn: dnsFilterApi.updateConfig,
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const addListMutation = useMutation({
|
||||
mutationFn: (data: { url: string; name: string }) => dnsFilterApi.addList(data),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const removeListMutation = useMutation({
|
||||
mutationFn: (id: string) => dnsFilterApi.removeList(id),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const toggleListMutation = useMutation({
|
||||
mutationFn: ({ id, enabled }: { id: string; enabled: boolean }) => dnsFilterApi.toggleList(id, enabled),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const addCustomMutation = useMutation({
|
||||
mutationFn: (entry: CustomEntry) => dnsFilterApi.setCustomEntry(entry),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const removeCustomMutation = useMutation({
|
||||
mutationFn: (domain: string) => dnsFilterApi.removeCustomEntry(domain),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
const triggerUpdateMutation = useMutation({
|
||||
mutationFn: () => dnsFilterApi.triggerUpdate(),
|
||||
onSuccess: () => {
|
||||
// Delay invalidation to give the runner time to download + compile
|
||||
setTimeout(invalidateAll, 3000);
|
||||
},
|
||||
});
|
||||
|
||||
const uploadListMutation = useMutation({
|
||||
mutationFn: ({ name, file }: { name: string; file: File }) => dnsFilterApi.uploadList(name, file),
|
||||
onSuccess: invalidateAll,
|
||||
});
|
||||
|
||||
return {
|
||||
status: statusQuery.data,
|
||||
isLoadingStatus: statusQuery.isLoading,
|
||||
config: configQuery.data,
|
||||
lists: listsQuery.data?.lists ?? [],
|
||||
customEntries: customQuery.data?.customEntries ?? [],
|
||||
suggestedLists: suggestedQuery.data?.lists ?? [],
|
||||
updateConfig: updateConfigMutation.mutateAsync,
|
||||
isUpdatingConfig: updateConfigMutation.isPending,
|
||||
addList: addListMutation.mutateAsync,
|
||||
isAddingList: addListMutation.isPending,
|
||||
removeList: removeListMutation.mutateAsync,
|
||||
toggleList: toggleListMutation.mutateAsync,
|
||||
addCustomEntry: addCustomMutation.mutateAsync,
|
||||
removeCustomEntry: removeCustomMutation.mutateAsync,
|
||||
triggerUpdate: triggerUpdateMutation.mutateAsync,
|
||||
isUpdating: triggerUpdateMutation.isPending,
|
||||
uploadList: uploadListMutation.mutateAsync,
|
||||
isUploading: uploadListMutation.isPending,
|
||||
refetch: invalidateAll,
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user