Migrate Phase 1 Functions

Migrate 8 high-priority functions (admin-delete-user, mfa-unenroll, confirm-account-deletion, request-account-deletion, send-contact-message, upload-image, validate-email-backend, process-oauth-profile) to wrapEdgeFunction pattern. Replace manual CORS/auth, add shared validations, integrate standardized error handling, and preserve existing rate limiting where applicable. Update implementations to leverage context span, requestId, and improved logging for consistent error reporting and tracing.
This commit is contained in:
gpt-engineer-app[bot]
2025-11-11 03:03:26 +00:00
parent 7181fdbcac
commit e28dc97d71
8 changed files with 394 additions and 1471 deletions

View File

@@ -1,13 +1,7 @@
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.39.3';
import { corsHeaders } from '../_shared/cors.ts';
import { rateLimiters, withRateLimit } from '../_shared/rateLimiter.ts';
import { edgeLogger } from "../_shared/logger.ts";
import { formatEdgeError } from "../_shared/errorFormatter.ts";
// Simple request tracking
const startRequest = () => ({ requestId: crypto.randomUUID(), start: Date.now() });
const endRequest = (tracking: { start: number }) => Date.now() - tracking.start;
import { createEdgeFunction } from '../_shared/edgeFunctionWrapper.ts';
import { validateString } from '../_shared/typeValidation.ts';
// Common disposable email domains (subset for performance)
const DISPOSABLE_DOMAINS = new Set([
@@ -53,69 +47,29 @@ function validateEmailFormat(email: string): EmailValidationResult {
}
// Apply lenient rate limiting (30 req/min) for email validation
// Users may need to validate multiple times during signup/profile update
serve(withRateLimit(async (req) => {
const tracking = startRequest();
// Handle CORS preflight requests
if (req.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders });
}
try {
const handler = createEdgeFunction(
{
name: 'validate-email-backend',
requireAuth: false,
corsHeaders: corsHeaders
},
async (req, context) => {
const { email } = await req.json();
validateString(email, 'email', { requestId: context.requestId });
if (!email || typeof email !== 'string') {
return new Response(
JSON.stringify({ valid: false, reason: 'Email is required', requestId: tracking.requestId }),
{
status: 400,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
}
);
}
context.span.setAttribute('action', 'validate_email');
// Validate email
const result = validateEmailFormat(email.toLowerCase().trim());
const duration = endRequest(tracking);
return new Response(
JSON.stringify({ ...result, requestId: tracking.requestId }),
JSON.stringify(result),
{
status: 200,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
}
);
} catch (error) {
const duration = endRequest(tracking);
const errorMessage = formatEdgeError(error);
edgeLogger.error('Email validation error', {
error: errorMessage,
requestId: tracking.requestId,
duration
});
return new Response(
JSON.stringify({
valid: false,
reason: 'Failed to validate email. Please try again.',
requestId: tracking.requestId
}),
{
status: 500,
headers: {
...corsHeaders,
'Content-Type': 'application/json',
'X-Request-ID': tracking.requestId
}
headers: { 'Content-Type': 'application/json' }
}
);
}
}, rateLimiters.lenient, corsHeaders));
);
export default withRateLimit(handler, rateLimiters.lenient, corsHeaders);