import { serve } from 'https://deno.land/std@0.190.0/http/server.ts'; import { createEdgeFunction, type EdgeFunctionContext } from '../_shared/edgeFunctionWrapper.ts'; import { corsHeaders } from '../_shared/cors.ts'; import { getRecentMetrics, getMetricsStats, getFunctionMetrics, getUserMetrics, getIPMetrics, clearMetrics, } from '../_shared/rateLimitMetrics.ts'; const handler = async (req: Request, { supabase, user, span, requestId }: EdgeFunctionContext) => { // Check if user has admin or moderator role const { data: roles } = await supabase .from('user_roles') .select('role') .eq('user_id', user.id); const userRoles = roles?.map((r: any) => r.role) || []; const isAuthorized = userRoles.some((role: string) => ['admin', 'moderator', 'superuser'].includes(role) ); if (!isAuthorized) { throw new Error('Insufficient permissions'); } // Parse query parameters const url = new URL(req.url); const action = url.searchParams.get('action') || 'stats'; const limit = parseInt(url.searchParams.get('limit') || '100', 10); const timeWindow = parseInt(url.searchParams.get('timeWindow') || '60000', 10); const functionName = url.searchParams.get('functionName'); const userId = url.searchParams.get('userId'); const clientIP = url.searchParams.get('clientIP'); let responseData: any; // Route to appropriate metrics handler switch (action) { case 'recent': responseData = { metrics: getRecentMetrics(limit), count: getRecentMetrics(limit).length, }; break; case 'stats': responseData = getMetricsStats(timeWindow); break; case 'function': if (!functionName) { throw new Error('functionName parameter required for function action'); } responseData = { functionName, metrics: getFunctionMetrics(functionName, limit), count: getFunctionMetrics(functionName, limit).length, }; break; case 'user': if (!userId) { throw new Error('userId parameter required for user action'); } responseData = { userId, metrics: getUserMetrics(userId, limit), count: getUserMetrics(userId, limit).length, }; break; case 'ip': if (!clientIP) { throw new Error('clientIP parameter required for ip action'); } responseData = { clientIP, metrics: getIPMetrics(clientIP, limit), count: getIPMetrics(clientIP, limit).length, }; break; case 'clear': // Only superusers can clear metrics const isSuperuser = userRoles.includes('superuser'); if (!isSuperuser) { throw new Error('Only superusers can clear metrics'); } clearMetrics(); responseData = { success: true, message: 'Metrics cleared' }; break; default: throw new Error('Invalid action. Valid actions: recent, stats, function, user, ip, clear'); } return responseData; }; serve(createEdgeFunction({ name: 'rate-limit-metrics', requireAuth: true, corsHeaders, enableTracing: true, rateLimitTier: 'lenient', }, handler));