Fix submission deletion and image cleanup

This commit is contained in:
gpt-engineer-app[bot]
2025-09-29 00:51:50 +00:00
parent f9778dd9d9
commit f3c4d97992

View File

@@ -299,32 +299,77 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
setActionLoading(item.id);
try {
console.log('Starting deletion process for submission:', item.id);
// Step 1: Extract photo IDs from the submission content
const photoIds: string[] = [];
const validImageIds: string[] = [];
const skippedPhotos: string[] = [];
if (item.content?.photos && Array.isArray(item.content.photos)) {
for (const photo of item.content.photos) {
if (photo.url) {
// Extract UUID from blob URL: blob:https://domain/[uuid]
// Check if this looks like a Cloudflare image ID (not a blob URL)
if (photo.url.startsWith('blob:')) {
// This is a blob URL - we can't extract a valid Cloudflare image ID
console.warn('Skipping blob URL (cannot extract Cloudflare image ID):', photo.url);
skippedPhotos.push(photo.url);
} else {
// Try to extract image ID from various URL formats
let imageId = '';
// If it's already just an ID
if (photo.url.match(/^[a-f0-9-]{36}$/)) {
imageId = photo.url;
} else {
// Extract from URL path
const urlParts = photo.url.split('/');
const imageId = urlParts[urlParts.length - 1];
// Basic UUID validation (should be at least 32 characters)
if (imageId && imageId.length >= 32) {
const lastPart = urlParts[urlParts.length - 1];
if (lastPart && lastPart.match(/^[a-f0-9-]{36}$/)) {
imageId = lastPart;
}
}
if (imageId) {
photoIds.push(imageId);
validImageIds.push(imageId);
} else {
console.warn('Could not extract valid image ID from URL:', photo.url);
skippedPhotos.push(photo.url);
}
}
}
}
}
// Step 2: Delete photos from Cloudflare Images (if any)
if (photoIds.length > 0) {
const deletePromises = photoIds.map(async (imageId) => {
console.log(`Found ${validImageIds.length} valid image IDs to delete, ${skippedPhotos.length} photos will be orphaned`);
// Step 2: Delete photos from Cloudflare Images (if any valid IDs)
if (validImageIds.length > 0) {
const deletePromises = validImageIds.map(async (imageId) => {
try {
await supabase.functions.invoke('upload-image', {
console.log('Attempting to delete image from Cloudflare:', imageId);
// Direct fetch call to the edge function with proper DELETE method
const response = await fetch('https://ydvtmnrszybqnbcqbdcy.supabase.co/functions/v1/upload-image', {
method: 'DELETE',
body: { imageId }
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6InlkdnRtbnJzenlicW5iY3FiZGN5Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3NTgzMjYzNTYsImV4cCI6MjA3MzkwMjM1Nn0.DM3oyapd_omP5ZzIlrT0H9qBsiQBxBRgw2tYuqgXKX4`
},
body: JSON.stringify({ imageId })
});
if (!response.ok) {
const errorData = await response.text();
throw new Error(`HTTP ${response.status}: ${errorData}`);
}
const result = await response.json();
console.log('Successfully deleted image:', imageId, result);
} catch (deleteError) {
console.warn(`Failed to delete photo ${imageId} from Cloudflare:`, deleteError);
console.error(`Failed to delete photo ${imageId} from Cloudflare:`, deleteError);
// Continue with other deletions - don't fail the entire operation
}
});
@@ -334,16 +379,34 @@ export const ModerationQueue = forwardRef<ModerationQueueRef>((props, ref) => {
}
// Step 3: Delete the submission from the database
console.log('Deleting submission from database:', item.id);
const { error } = await supabase
.from('content_submissions')
.delete()
.eq('id', item.id);
if (error) throw error;
if (error) {
console.error('Database deletion error:', error);
throw error;
}
console.log('Submission successfully deleted from database');
const deletedCount = validImageIds.length;
const orphanedCount = skippedPhotos.length;
let description = 'The submission has been permanently deleted';
if (deletedCount > 0 && orphanedCount > 0) {
description = `The submission and ${deletedCount} photo(s) have been deleted. ${orphanedCount} photo(s) could not be deleted from storage (orphaned blob URLs)`;
} else if (deletedCount > 0) {
description = `The submission and ${deletedCount} associated photo(s) have been permanently deleted`;
} else if (orphanedCount > 0) {
description = `The submission has been deleted. ${orphanedCount} photo(s) could not be deleted from storage (orphaned blob URLs)`;
}
toast({
title: "Submission deleted",
description: `The submission and ${photoIds.length > 0 ? `${photoIds.length} associated photo(s) have` : 'has'} been permanently deleted`,
description,
});
// Remove item from the current view