Fix edge function console statements

This commit is contained in:
gpt-engineer-app[bot]
2025-11-03 19:09:28 +00:00
parent 7663205512
commit c0f468451f
8 changed files with 92 additions and 64 deletions

View File

@@ -87,7 +87,7 @@ serve(async (req) => {
.limit(1);
if (rateLimitError) {
console.error('[Export] Rate limit check failed:', rateLimitError);
edgeLogger.error('Rate limit check failed', { action: 'export_rate_limit', requestId: tracking.requestId, error: rateLimitError });
}
if (recentExports && recentExports.length > 0) {

View File

@@ -1,7 +1,7 @@
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { Novu } from "npm:@novu/api@1.6.0";
import { startRequest, endRequest } from "../_shared/logger.ts";
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -38,7 +38,7 @@ serve(async (req) => {
throw new Error('Action must be either "add" or "remove"');
}
console.log(`${action === 'add' ? 'Adding' : 'Removing'} user ${userId} ${action === 'add' ? 'to' : 'from'} moderator topics`, { requestId: tracking.requestId });
edgeLogger.info(`${action === 'add' ? 'Adding' : 'Removing'} user ${userId} ${action === 'add' ? 'to' : 'from'} moderator topics`, { action: 'manage_moderator_topic', requestId: tracking.requestId, userId, operation: action });
const topics = [TOPICS.MODERATION_SUBMISSIONS, TOPICS.MODERATION_REPORTS];
const results = [];
@@ -50,18 +50,24 @@ serve(async (req) => {
await novu.topics.addSubscribers(topicKey, {
subscribers: [userId],
});
console.log(`Added ${userId} to topic ${topicKey}`);
edgeLogger.info('Added user to topic', { action: 'manage_moderator_topic', requestId: tracking.requestId, userId, topicKey });
results.push({ topic: topicKey, action: 'added', success: true });
} else {
// Remove subscriber from topic
await novu.topics.removeSubscribers(topicKey, {
subscribers: [userId],
});
console.log(`Removed ${userId} from topic ${topicKey}`);
edgeLogger.info('Removed user from topic', { action: 'manage_moderator_topic', requestId: tracking.requestId, userId, topicKey });
results.push({ topic: topicKey, action: 'removed', success: true });
}
} catch (error: any) {
console.error(`Error ${action}ing user ${userId} ${action === 'add' ? 'to' : 'from'} topic ${topicKey}:`, error);
edgeLogger.error(`Error ${action}ing user ${userId} ${action === 'add' ? 'to' : 'from'} topic ${topicKey}`, {
action: 'manage_moderator_topic',
requestId: tracking.requestId,
userId,
topicKey,
error: error.message
});
results.push({
topic: topicKey,
action: action === 'add' ? 'added' : 'removed',
@@ -93,7 +99,7 @@ serve(async (req) => {
}
);
} catch (error: any) {
console.error('Error managing moderator topic:', error);
edgeLogger.error('Error managing moderator topic', { action: 'manage_moderator_topic', requestId: tracking.requestId, error: error.message });
endRequest(tracking, 500, error.message);

View File

@@ -1,7 +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.57.4";
import { Novu } from "npm:@novu/api@1.6.0";
import { startRequest, endRequest } from "../_shared/logger.ts";
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -156,7 +156,7 @@ serve(async (req) => {
}
);
} catch (error: any) {
console.error('Error migrating Novu users:', error);
edgeLogger.error('Error migrating Novu users', { action: 'migrate_novu_users', requestId: tracking.requestId, error: error.message });
endRequest(tracking, 500, error.message);

View File

@@ -1,6 +1,6 @@
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { startRequest, endRequest } from "../_shared/logger.ts";
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -33,7 +33,8 @@ serve(async (req) => {
const payload: NotificationPayload = await req.json();
console.log('Processing report notification:', {
edgeLogger.info('Processing report notification', {
action: 'notify_moderators_report',
reportId: payload.reportId,
reportType: payload.reportType,
reportedEntityType: payload.reportedEntityType,
@@ -78,12 +79,12 @@ serve(async (req) => {
.maybeSingle();
if (templateError) {
console.error('Error fetching workflow:', templateError);
edgeLogger.error('Error fetching workflow', { action: 'notify_moderators_report', requestId: tracking.requestId, error: templateError });
throw new Error(`Failed to fetch workflow: ${templateError.message}`);
}
if (!template) {
console.warn('No active report-alert workflow found');
edgeLogger.warn('No active report-alert workflow found', { action: 'notify_moderators_report', requestId: tracking.requestId });
return new Response(
JSON.stringify({
success: false,
@@ -126,7 +127,7 @@ serve(async (req) => {
reportedEntityName = submission?.content?.name || 'Submission';
}
} catch (error) {
console.warn('Could not fetch entity name:', error);
edgeLogger.warn('Could not fetch entity name', { action: 'notify_moderators_report', requestId: tracking.requestId, error });
}
// Build enhanced notification payload
@@ -145,7 +146,7 @@ serve(async (req) => {
priority,
};
console.log('Triggering notification with payload:', notificationPayload);
edgeLogger.info('Triggering notification with payload', { action: 'notify_moderators_report', requestId: tracking.requestId });
// Invoke the trigger-notification function
const { data: result, error: notifyError } = await supabase.functions.invoke(
@@ -160,11 +161,11 @@ serve(async (req) => {
);
if (notifyError) {
console.error('Error triggering notification:', notifyError);
edgeLogger.error('Error triggering notification', { action: 'notify_moderators_report', requestId: tracking.requestId, error: notifyError });
throw notifyError;
}
console.log('Notification triggered successfully:', result);
edgeLogger.info('Notification triggered successfully', { action: 'notify_moderators_report', requestId: tracking.requestId, result });
endRequest(tracking, 200);
@@ -185,7 +186,7 @@ serve(async (req) => {
}
);
} catch (error: any) {
console.error('Error in notify-moderators-report:', error);
edgeLogger.error('Error in notify-moderators-report', { action: 'notify_moderators_report', requestId: tracking.requestId, error: error.message });
endRequest(tracking, 500, error.message);

View File

@@ -1,6 +1,6 @@
import { serve } from "https://deno.land/std@0.168.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { startRequest, endRequest } from "../_shared/logger.ts";
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -70,7 +70,8 @@ serve(async (req) => {
throw new Error('Invalid severity level. Must be: info, warning, or critical');
}
console.log('Processing system announcement:', {
edgeLogger.info('Processing system announcement', {
action: 'notify_system_announcement',
title: payload.title,
severity: payload.severity,
publishedBy: profile?.username || 'unknown',
@@ -86,12 +87,12 @@ serve(async (req) => {
.maybeSingle();
if (templateError) {
console.error('Error fetching workflow:', templateError);
edgeLogger.error('Error fetching workflow', { action: 'notify_system_announcement', requestId: tracking.requestId, error: templateError });
throw new Error(`Failed to fetch workflow: ${templateError.message}`);
}
if (!template) {
console.warn('No active system-announcement workflow found');
edgeLogger.warn('No active system-announcement workflow found', { action: 'notify_system_announcement', requestId: tracking.requestId });
return new Response(
JSON.stringify({
success: false,
@@ -120,7 +121,7 @@ serve(async (req) => {
publishedBy,
};
console.log('Triggering announcement to all users via "users" topic');
edgeLogger.info('Triggering announcement to all users via "users" topic', { action: 'notify_system_announcement', requestId: tracking.requestId });
// Invoke the trigger-notification function with users topic
const { data: result, error: notifyError } = await supabase.functions.invoke(
@@ -135,11 +136,11 @@ serve(async (req) => {
);
if (notifyError) {
console.error('Error triggering notification:', notifyError);
edgeLogger.error('Error triggering notification', { action: 'notify_system_announcement', requestId: tracking.requestId, error: notifyError });
throw notifyError;
}
console.log('System announcement triggered successfully:', result);
edgeLogger.info('System announcement triggered successfully', { action: 'notify_system_announcement', requestId: tracking.requestId, result });
endRequest(tracking, 200);
@@ -161,7 +162,7 @@ serve(async (req) => {
}
);
} catch (error: any) {
console.error('Error in notify-system-announcement:', error);
edgeLogger.error('Error in notify-system-announcement', { action: 'notify_system_announcement', requestId: tracking.requestId, error: error.message });
endRequest(tracking, error.message.includes('Unauthorized') ? 403 : 500, error.message);

View File

@@ -1,6 +1,6 @@
import { serve } from "https://deno.land/std@0.190.0/http/server.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { startRequest, endRequest } from "../_shared/logger.ts";
import { edgeLogger, startRequest, endRequest } from "../_shared/logger.ts";
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -176,7 +176,8 @@ serve(async (req) => {
is_duplicate: true
}).eq('id', existingLog.id);
console.log('Duplicate notification prevented:', {
edgeLogger.info('Duplicate notification prevented', {
action: 'notify_user_submission_status',
userId: user_id,
idempotencyKey,
submissionId: submission_id,
@@ -203,7 +204,8 @@ serve(async (req) => {
);
}
console.log('Sending notification to user:', {
edgeLogger.info('Sending notification to user', {
action: 'notify_user_submission_status',
userId: user_id,
workflowId,
entityName,
@@ -241,7 +243,7 @@ serve(async (req) => {
}
});
console.log('User notification sent successfully:', notificationResult);
edgeLogger.info('User notification sent successfully', { action: 'notify_user_submission_status', requestId: tracking.requestId, result: notificationResult });
endRequest(tracking, 200);
@@ -262,7 +264,7 @@ serve(async (req) => {
);
} catch (error: unknown) {
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
console.error('Error notifying user about submission status:', errorMessage);
edgeLogger.error('Error notifying user about submission status', { action: 'notify_user_submission_status', requestId: tracking.requestId, error: errorMessage });
endRequest(tracking, 500, errorMessage);

View File

@@ -1,4 +1,5 @@
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2.57.4';
import { edgeLogger } from '../_shared/logger.ts';
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -35,16 +36,16 @@ Deno.serve(async (req) => {
.lte('ban_expires_at', now);
if (fetchError) {
console.error('Error fetching expired bans:', fetchError);
edgeLogger.error('Error fetching expired bans', { action: 'process_expired_bans', error: fetchError });
throw fetchError;
}
console.log(`Found ${expiredBans?.length || 0} expired bans to process`);
edgeLogger.info(`Found ${expiredBans?.length || 0} expired bans to process`, { action: 'process_expired_bans', count: expiredBans?.length || 0 });
// Unban users with expired bans
const unbannedUsers: string[] = [];
for (const profile of expiredBans || []) {
console.log(`Unbanning user: ${profile.username} (${profile.user_id})`);
edgeLogger.info('Unbanning user', { action: 'process_expired_bans', username: profile.username, userId: profile.user_id });
const { error: unbanError } = await supabaseAdmin
.from('profiles')
@@ -56,7 +57,7 @@ Deno.serve(async (req) => {
.eq('user_id', profile.user_id);
if (unbanError) {
console.error(`Failed to unban ${profile.username}:`, unbanError);
edgeLogger.error('Failed to unban user', { action: 'process_expired_bans', username: profile.username, error: unbanError });
continue;
}
@@ -74,13 +75,13 @@ Deno.serve(async (req) => {
});
if (logError) {
console.error(`Failed to log auto-unban for ${profile.username}:`, logError);
edgeLogger.error('Failed to log auto-unban', { action: 'process_expired_bans', username: profile.username, error: logError });
}
unbannedUsers.push(profile.username);
}
console.log(`Successfully unbanned ${unbannedUsers.length} users`);
edgeLogger.info('Successfully unbanned users', { action: 'process_expired_bans', count: unbannedUsers.length });
return new Response(
JSON.stringify({
@@ -96,7 +97,7 @@ Deno.serve(async (req) => {
);
} catch (error) {
console.error('Error in process-expired-bans:', error);
edgeLogger.error('Error in process-expired-bans', { action: 'process_expired_bans', error });
return new Response(
JSON.stringify({
error: error instanceof Error ? error.message : 'Unknown error',

View File

@@ -1,6 +1,6 @@
import "jsr:@supabase/functions-js/edge-runtime.d.ts";
import { createClient } from "https://esm.sh/@supabase/supabase-js@2.57.4";
import { startRequest, endRequest } from '../_shared/logger.ts';
import { edgeLogger, startRequest, endRequest } from '../_shared/logger.ts';
const corsHeaders = {
'Access-Control-Allow-Origin': '*',
@@ -12,11 +12,14 @@ const CLOUDFLARE_API_TOKEN = Deno.env.get('CLOUDFLARE_IMAGES_API_TOKEN');
// Validate configuration at startup
if (!CLOUDFLARE_ACCOUNT_ID || !CLOUDFLARE_API_TOKEN) {
console.error('[OAuth Profile] Missing Cloudflare configuration:', {
edgeLogger.error('Missing Cloudflare configuration', {
action: 'oauth_profile_init',
hasAccountId: !!CLOUDFLARE_ACCOUNT_ID,
hasApiToken: !!CLOUDFLARE_API_TOKEN,
});
console.error('[OAuth Profile] Please configure CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_IMAGES_API_TOKEN in Supabase Edge Function secrets');
edgeLogger.error('Please configure CLOUDFLARE_ACCOUNT_ID and CLOUDFLARE_IMAGES_API_TOKEN in Supabase Edge Function secrets', {
action: 'oauth_profile_init'
});
}
interface GoogleUserMetadata {
@@ -96,14 +99,14 @@ Deno.serve(async (req) => {
const { data: { user }, error: authError } = await supabase.auth.getUser(token);
if (authError || !user) {
console.error('[OAuth Profile] Authentication failed:', authError);
edgeLogger.error('Authentication failed', { action: 'oauth_profile', error: authError, requestId: tracking.requestId });
return new Response(JSON.stringify({ error: 'Unauthorized' }), {
status: 401,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
console.log('[OAuth Profile] Processing profile for user:', user.id);
edgeLogger.info('Processing profile for user', { action: 'oauth_profile', userId: user.id, requestId: tracking.requestId });
// CRITICAL: Check ban status immediately
const { data: banProfile } = await supabase
@@ -118,7 +121,8 @@ Deno.serve(async (req) => {
? `Your account has been suspended. Reason: ${banProfile.ban_reason}`
: 'Your account has been suspended. Contact support for assistance.';
console.log('[OAuth Profile] User is banned, rejecting authentication', {
edgeLogger.info('User is banned, rejecting authentication', {
action: 'oauth_profile_banned',
requestId: tracking.requestId,
duration,
hasBanReason: !!banProfile.ban_reason
@@ -144,7 +148,9 @@ Deno.serve(async (req) => {
if (discordIdentity) {
userMetadata = discordIdentity.identity_data || {};
console.log('[OAuth Profile] Discord identity_data:', {
edgeLogger.info('Discord identity_data', {
action: 'oauth_profile_discord',
requestId: tracking.requestId,
hasAvatarUrl: !!(userMetadata as DiscordUserMetadata).avatar_url,
hasFullName: !!(userMetadata as DiscordUserMetadata).full_name,
hasGlobalName: !!(userMetadata as DiscordUserMetadata).custom_claims?.global_name,
@@ -152,7 +158,7 @@ Deno.serve(async (req) => {
hasEmail: !!(userMetadata as DiscordUserMetadata).email
});
} else {
console.warn('[OAuth Profile] Discord provider found but no Discord identity in user.identities');
edgeLogger.warn('Discord provider found but no Discord identity in user.identities', { action: 'oauth_profile_discord', requestId: tracking.requestId });
}
}
@@ -166,7 +172,7 @@ Deno.serve(async (req) => {
avatarUrl = googleData.picture || null;
displayName = googleData.name || null;
usernameBase = googleData.email?.split('@')[0] || null;
console.log('[OAuth Profile] Google user:', { avatarUrl, displayName, usernameBase });
edgeLogger.info('Google user', { action: 'oauth_profile_google', requestId: tracking.requestId, avatarUrl, displayName, usernameBase });
} else if (provider === 'discord') {
const discordData = userMetadata as DiscordUserMetadata;
@@ -187,15 +193,17 @@ Deno.serve(async (req) => {
// Validation logging
if (!discordId) {
console.error('[OAuth Profile] Discord user ID missing from provider_id/sub - OAuth data incomplete');
edgeLogger.error('Discord user ID missing from provider_id/sub - OAuth data incomplete', { action: 'oauth_profile_discord', requestId: tracking.requestId });
}
if (!usernameBase) {
console.warn('[OAuth Profile] Discord username missing - using ID as fallback');
edgeLogger.warn('Discord username missing - using ID as fallback', { action: 'oauth_profile_discord', requestId: tracking.requestId });
usernameBase = discordId;
}
console.log('[OAuth Profile] Discord user (Supabase format):', {
edgeLogger.info('Discord user (Supabase format)', {
action: 'oauth_profile_discord',
requestId: tracking.requestId,
avatarUrl,
displayName,
usernameBase,
@@ -205,7 +213,7 @@ Deno.serve(async (req) => {
source: discordData.avatar_url ? 'avatar_url' : discordData.picture ? 'picture' : 'none'
});
} else {
console.log('[OAuth Profile] Unsupported provider:', provider);
edgeLogger.info('Unsupported provider', { action: 'oauth_profile', provider, requestId: tracking.requestId });
return new Response(JSON.stringify({ success: true, message: 'Provider not supported' }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
@@ -220,7 +228,7 @@ Deno.serve(async (req) => {
if (profile?.avatar_image_id) {
const duration = endRequest(tracking);
console.log('[OAuth Profile] Avatar already exists, skipping', { requestId: tracking.requestId, duration });
edgeLogger.info('Avatar already exists, skipping', { action: 'oauth_profile', requestId: tracking.requestId, duration });
return new Response(JSON.stringify({ success: true, message: 'Avatar already exists', requestId: tracking.requestId }), {
headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId },
});
@@ -233,14 +241,19 @@ Deno.serve(async (req) => {
if (avatarUrl) {
// Validate secrets before attempting upload
if (!CLOUDFLARE_ACCOUNT_ID || !CLOUDFLARE_API_TOKEN) {
console.warn('[OAuth Profile] Cloudflare secrets not configured, skipping avatar upload');
console.warn('[OAuth Profile] Missing:', {
edgeLogger.warn('Cloudflare secrets not configured, skipping avatar upload', {
action: 'oauth_profile_upload',
requestId: tracking.requestId
});
edgeLogger.warn('Missing Cloudflare configuration', {
action: 'oauth_profile_upload',
requestId: tracking.requestId,
accountId: !CLOUDFLARE_ACCOUNT_ID,
apiToken: !CLOUDFLARE_API_TOKEN,
});
} else {
try {
console.log('[OAuth Profile] Downloading avatar from:', avatarUrl);
edgeLogger.info('Downloading avatar', { action: 'oauth_profile_upload', avatarUrl, requestId: tracking.requestId });
// Download image with timeout
const controller = new AbortController();
@@ -262,7 +275,9 @@ Deno.serve(async (req) => {
throw new Error('Image too large (max 10MB)');
}
console.log('[OAuth Profile] Downloaded image:', {
edgeLogger.info('Downloaded image', {
action: 'oauth_profile_upload',
requestId: tracking.requestId,
size: imageBlob.size,
type: imageBlob.type,
});
@@ -285,7 +300,7 @@ Deno.serve(async (req) => {
const uploadData = await uploadUrlResponse.json();
const uploadURL = uploadData.result.uploadURL;
console.log('[OAuth Profile] Got Cloudflare upload URL');
edgeLogger.info('Got Cloudflare upload URL', { action: 'oauth_profile_upload', requestId: tracking.requestId });
// Upload to Cloudflare
const formData = new FormData();
@@ -305,12 +320,14 @@ Deno.serve(async (req) => {
if (result.success) {
cloudflareImageId = result.result.id;
cloudflareImageUrl = `https://cdn.thrillwiki.com/images/${cloudflareImageId}/avatar`;
console.log('[OAuth Profile] Uploaded to Cloudflare:', { cloudflareImageId, cloudflareImageUrl });
edgeLogger.info('Uploaded to Cloudflare', { action: 'oauth_profile_upload', requestId: tracking.requestId, cloudflareImageId, cloudflareImageUrl });
} else {
throw new Error('Cloudflare upload failed');
}
} catch (error) {
console.error('[OAuth Profile] Avatar upload failed:', {
edgeLogger.error('Avatar upload failed', {
action: 'oauth_profile_upload',
requestId: tracking.requestId,
error: error.message,
provider: provider,
accountId: CLOUDFLARE_ACCOUNT_ID,
@@ -338,7 +355,7 @@ Deno.serve(async (req) => {
if (usernameBase && profile?.username?.startsWith('user_')) {
const newUsername = await ensureUniqueUsername(supabase, usernameBase, user.id);
updateData.username = newUsername;
console.log('[OAuth Profile] Updating generic username from', profile.username, 'to', newUsername);
edgeLogger.info('Updating generic username', { action: 'oauth_profile', requestId: tracking.requestId, oldUsername: profile.username, newUsername });
}
// Only update if we have data to update
@@ -349,18 +366,18 @@ Deno.serve(async (req) => {
.eq('user_id', user.id);
if (updateError) {
console.error('[OAuth Profile] Failed to update profile:', updateError);
edgeLogger.error('Failed to update profile', { action: 'oauth_profile', requestId: tracking.requestId, error: updateError });
return new Response(JSON.stringify({ error: 'Failed to update profile' }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
console.log('[OAuth Profile] Profile updated successfully', { requestId: tracking.requestId });
edgeLogger.info('Profile updated successfully', { action: 'oauth_profile', requestId: tracking.requestId });
}
const duration = endRequest(tracking);
console.log('[OAuth Profile] Processing complete', { requestId: tracking.requestId, duration });
edgeLogger.info('Processing complete', { action: 'oauth_profile', requestId: tracking.requestId, duration });
return new Response(JSON.stringify({
success: true,
@@ -373,7 +390,7 @@ Deno.serve(async (req) => {
} catch (error) {
const duration = endRequest(tracking);
console.error('[OAuth Profile] Error:', error, { requestId: tracking.requestId, duration });
edgeLogger.error('Error in oauth profile processing', { action: 'oauth_profile', requestId: tracking.requestId, duration, error: error.message });
return new Response(JSON.stringify({ error: error.message, requestId: tracking.requestId }), {
status: 500,
headers: { ...corsHeaders, 'Content-Type': 'application/json', 'X-Request-ID': tracking.requestId },