import { PermissionAction } from '@supabase/shared-types/out/constants' import { useParams } from 'common' import { Globe } from 'lucide-react' import { useState } from 'react' import { toast } from 'sonner' import { Badge, Card, CardContent, Skeleton } from 'ui' import { PageSection, PageSectionContent, PageSectionDescription, PageSectionMeta, PageSectionSummary, PageSectionTitle, } from 'ui-patterns' import ConfirmationModal from 'ui-patterns/Dialogs/ConfirmationModal' import AlertError from '@/components/ui/AlertError' import { ButtonTooltip } from '@/components/ui/ButtonTooltip' import { DocsButton } from '@/components/ui/DocsButton' import { useBannedIPsDeleteMutation } from '@/data/banned-ips/banned-ips-delete-mutations' import { useBannedIPsQuery } from '@/data/banned-ips/banned-ips-query' import { useUserIPAddressQuery } from '@/data/misc/user-ip-address-query' import { useAsyncCheckPermissions } from '@/hooks/misc/useCheckPermissions' import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject' import { DOCS_URL } from '@/lib/constants' export const BannedIPs = () => { const { ref } = useParams() const { data: project } = useSelectedProjectQuery() const [selectedIPToUnban, setSelectedIPToUnban] = useState(null) // Track the selected IP for unban const { isPending: isLoadingIPList, isFetching: isFetchingIPList, data: ipList, error: ipListError, } = useBannedIPsQuery({ projectRef: ref, }) const { data: userIPAddress } = useUserIPAddressQuery() const ipListLoading = isLoadingIPList || isFetchingIPList const [showUnban, setShowUnban] = useState(false) const [confirmingIP, setConfirmingIP] = useState(null) // Track the IP being confirmed for unban const { can: canUnbanNetworks } = useAsyncCheckPermissions(PermissionAction.UPDATE, 'projects', { resource: { project_id: project?.id, }, }) const { mutate: unbanIPs, isPending: isUnbanning } = useBannedIPsDeleteMutation({ onSuccess: () => { toast.success('IP address successfully unbanned') setSelectedIPToUnban(null) // Reset the selected IP for unban setShowUnban(false) }, onError: (error) => { toast.error(`Failed to unban IP: ${error?.message}`) }, }) const onConfirmUnbanIP = () => { if (confirmingIP == null || !ref) return unbanIPs({ projectRef: ref, ips: [confirmingIP], // Pass the IP as an array }) } const openConfirmationModal = (ip: string) => { setSelectedIPToUnban(ip) // Set the selected IP for unban setConfirmingIP(ip) // Set the IP being confirmed for unban setShowUnban(true) } return ( <> Network bans IP addresses temporarily blocked due to suspicious traffic {ipListLoading ? ( ) : ipListError ? ( ) : ipList.banned_ipv4_addresses.length > 0 ? ( {ipList.banned_ipv4_addresses.map((ip) => (

{ip}

{ip === userIPAddress && Your IP address}
openConfirmationModal(ip)} tooltip={{ content: { side: 'bottom', text: !canUnbanNetworks ? 'You need additional permissions to unban networks' : undefined, }, }} > Unban IP
))}
) : ( There are no banned IP addresses for your project )}
setShowUnban(false)} onConfirm={onConfirmUnbanIP} alert={{ title: 'This action cannot be undone', description: `Are you sure you want to unban this IP address ${selectedIPToUnban}?`, }} /> ) }