import { useState, useEffect } from 'react' import { Gauge, Info } from 'lucide-react' import { Button } from '../components/ui/Button' import { Input } from '../components/ui/Input' import { Card } from '../components/ui/Card' import { useSecurityStatus, useSecurityConfig, useUpdateSecurityConfig } from '../hooks/useSecurity' import { updateSetting } from '../api/settings' import { useMutation, useQueryClient } from '@tanstack/react-query' import { toast } from '../utils/toast' import { ConfigReloadOverlay } from '../components/LoadingStates' export default function RateLimiting() { const { data: status, isLoading: statusLoading } = useSecurityStatus() const { data: configData, isLoading: configLoading } = useSecurityConfig() const updateConfigMutation = useUpdateSecurityConfig() const queryClient = useQueryClient() const [rps, setRps] = useState(10) const [burst, setBurst] = useState(5) const [window, setWindow] = useState(60) const config = configData?.config // Sync local state with fetched config useEffect(() => { if (config) { setRps(config.rate_limit_requests ?? 10) setBurst(config.rate_limit_burst ?? 5) setWindow(config.rate_limit_window_sec ?? 60) } }, [config]) const toggleMutation = useMutation({ mutationFn: async (enabled: boolean) => { await updateSetting('security.rate_limit.enabled', enabled ? 'true' : 'false', 'security', 'bool') }, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['securityStatus'] }) toast.success('Rate limiting setting updated') }, onError: (err: Error) => { toast.error(`Failed to update: ${err.message}`) }, }) const handleToggle = () => { const newValue = !status?.rate_limit?.enabled toggleMutation.mutate(newValue) } const handleSave = () => { updateConfigMutation.mutate({ rate_limit_requests: rps, rate_limit_burst: burst, rate_limit_window_sec: window, }) } const isApplyingConfig = toggleMutation.isPending || updateConfigMutation.isPending if (statusLoading || configLoading) { return
Loading...
} const enabled = status?.rate_limit?.enabled ?? false return ( <> {isApplyingConfig && ( )}
{/* Header */}

Rate Limiting Configuration

Control request rates to protect your services from abuse

{/* Info Banner */}

About Rate Limiting

Rate limiting helps protect your services from abuse, brute-force attacks, and excessive resource consumption. Configure limits per client IP address.

{/* Active Settings Summary */} {enabled && config && (

Currently Active

{config.rate_limit_requests} requests/sec • Burst: {config.rate_limit_burst} • Window: {config.rate_limit_window_sec}s

)} {/* Enable/Disable Toggle */}

Enable Rate Limiting

{enabled ? 'Rate limiting is active and protecting your services' : 'Enable to start limiting request rates'}

{/* Configuration Section - Only visible when enabled */} {enabled && (

Configuration

setRps(parseInt(e.target.value, 10) || 1)} helperText="Maximum requests allowed per second per client" data-testid="rate-limit-rps" /> setBurst(parseInt(e.target.value, 10) || 1)} helperText="Allow short bursts above the rate limit" data-testid="rate-limit-burst" /> setWindow(parseInt(e.target.value, 10) || 1)} helperText="Time window for rate calculations" data-testid="rate-limit-window" />
)} {/* Guidance when disabled */} {!enabled && (
⏱️

Rate Limiting Disabled

Enable rate limiting to configure request limits and protect your services

)}
) }