mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 17:31:13 -05:00
Refactor process-expired-bans, detect-location, detect-anomalies, rate-limit-metrics, and collect-metrics to use createEdgeFunction wrapper with standardized error handling, tracing, and reduced boilerplate. Update signatures to receive { supabase, span, requestId } (and user where applicable), replace manual logging with span events, remove per-function boilerplate, and ensure consistent wrapper configuration (cors, auth, rate limits, and tracing).
110 lines
3.1 KiB
TypeScript
110 lines
3.1 KiB
TypeScript
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));
|