mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-23 01:51:13 -05:00
Improve image upload and test data generation functionalities
Refactors `uploadPendingImages` to use `Promise.allSettled` for parallel uploads and implements JSON path queries in `clearTestData` and `getTestDataStats` for more robust test data management. Enhances `seed-test-data` function to support creating data conflicts and version chains, and adds validation for `imageId` format in `upload-image` function. Updates `AutocompleteSearch` to use a default search types constant. Replit-Commit-Author: Agent Replit-Commit-Session-Id: dc31cf9d-7a06-4420-8ade-e7b7f5200e71 Replit-Commit-Checkpoint-Type: intermediate_checkpoint
This commit is contained in:
@@ -75,7 +75,7 @@ Deno.serve(async (req) => {
|
||||
}
|
||||
|
||||
// Parse request
|
||||
const { preset = 'small', entityTypes = [], includeDependencies = true, includeEscalated = false, includeExpiredLocks = false }: SeedOptions = await req.json();
|
||||
const { preset = 'small', entityTypes = [], includeDependencies = true, includeConflicts = false, includeVersionChains = false, includeEscalated = false, includeExpiredLocks = false }: SeedOptions = await req.json();
|
||||
const plan = PRESETS[preset];
|
||||
|
||||
if (!plan) {
|
||||
@@ -86,9 +86,11 @@ Deno.serve(async (req) => {
|
||||
}
|
||||
|
||||
const startTime = Date.now();
|
||||
const summary = { parks: 0, rides: 0, companies: 0, rideModels: 0 };
|
||||
const summary = { parks: 0, rides: 0, companies: 0, rideModels: 0, conflicts: 0, versionChains: 0 };
|
||||
const createdParks: string[] = [];
|
||||
const createdCompanies: Record<string, string[]> = { manufacturer: [], operator: [], designer: [], property_owner: [] };
|
||||
const createdParkSlugs: string[] = [];
|
||||
const createdRideSlugs: string[] = [];
|
||||
|
||||
// Helper to create submission
|
||||
async function createSubmission(userId: string, type: string, itemData: any, options: { escalated?: boolean; expiredLock?: boolean } = {}) {
|
||||
@@ -177,10 +179,25 @@ Deno.serve(async (req) => {
|
||||
// Create parks
|
||||
if (entityTypes.includes('parks')) {
|
||||
for (let i = 0; i < plan.parks; i++) {
|
||||
// Determine if this should be a conflict or version chain
|
||||
const shouldConflict = includeConflicts && createdParkSlugs.length > 0 && Math.random() < 0.15;
|
||||
const shouldVersionChain = includeVersionChains && createdParkSlugs.length > 0 && Math.random() < 0.15;
|
||||
|
||||
let slug = `test-park-${i + 1}`;
|
||||
if (shouldConflict) {
|
||||
// Reuse an existing slug to create a conflict
|
||||
slug = createdParkSlugs[Math.floor(Math.random() * createdParkSlugs.length)];
|
||||
summary.conflicts++;
|
||||
} else if (shouldVersionChain) {
|
||||
// Reuse an existing slug for a version chain with different data
|
||||
slug = createdParkSlugs[Math.floor(Math.random() * createdParkSlugs.length)];
|
||||
summary.versionChains++;
|
||||
}
|
||||
|
||||
const parkData = {
|
||||
name: `Test Park ${i + 1}`,
|
||||
slug: `test-park-${i + 1}`,
|
||||
description: 'Test park description',
|
||||
name: shouldVersionChain ? `Test Park ${slug} (Updated)` : `Test Park ${i + 1}`,
|
||||
slug: slug,
|
||||
description: shouldVersionChain ? 'Updated test park description' : 'Test park description',
|
||||
park_type: ['theme_park', 'amusement_park', 'water_park'][Math.floor(Math.random() * 3)],
|
||||
status: 'operating',
|
||||
opening_date: '2000-01-01'
|
||||
@@ -192,7 +209,10 @@ Deno.serve(async (req) => {
|
||||
};
|
||||
|
||||
await createSubmission(user.id, 'park', parkData, options);
|
||||
createdParks.push(`test-park-${i + 1}`);
|
||||
createdParks.push(slug);
|
||||
if (!shouldConflict && !shouldVersionChain) {
|
||||
createdParkSlugs.push(slug);
|
||||
}
|
||||
summary.parks++;
|
||||
}
|
||||
}
|
||||
@@ -222,6 +242,19 @@ Deno.serve(async (req) => {
|
||||
// Create rides (with dependencies if enabled)
|
||||
if (entityTypes.includes('rides') && includeDependencies && createdParks.length > 0) {
|
||||
for (let i = 0; i < plan.rides; i++) {
|
||||
// Determine if this should be a conflict or version chain
|
||||
const shouldConflict = includeConflicts && createdRideSlugs.length > 0 && Math.random() < 0.15;
|
||||
const shouldVersionChain = includeVersionChains && createdRideSlugs.length > 0 && Math.random() < 0.15;
|
||||
|
||||
let slug = `test-ride-${i + 1}`;
|
||||
if (shouldConflict) {
|
||||
slug = createdRideSlugs[Math.floor(Math.random() * createdRideSlugs.length)];
|
||||
summary.conflicts++;
|
||||
} else if (shouldVersionChain) {
|
||||
slug = createdRideSlugs[Math.floor(Math.random() * createdRideSlugs.length)];
|
||||
summary.versionChains++;
|
||||
}
|
||||
|
||||
// Get random park ID from database
|
||||
const parkSlug = createdParks[Math.floor(Math.random() * createdParks.length)];
|
||||
const { data: parkData } = await supabase
|
||||
@@ -231,9 +264,9 @@ Deno.serve(async (req) => {
|
||||
.maybeSingle();
|
||||
|
||||
const rideData = {
|
||||
name: `Test Ride ${i + 1}`,
|
||||
slug: `test-ride-${i + 1}`,
|
||||
description: 'Test ride description',
|
||||
name: shouldVersionChain ? `Test Ride ${slug} (Updated)` : `Test Ride ${i + 1}`,
|
||||
slug: slug,
|
||||
description: shouldVersionChain ? 'Updated test ride description' : 'Test ride description',
|
||||
category: ['roller_coaster', 'flat_ride', 'water_ride'][Math.floor(Math.random() * 3)],
|
||||
status: 'operating',
|
||||
park_id: parkData?.id || null,
|
||||
@@ -241,6 +274,9 @@ Deno.serve(async (req) => {
|
||||
};
|
||||
|
||||
await createSubmission(user.id, 'ride', rideData);
|
||||
if (!shouldConflict && !shouldVersionChain) {
|
||||
createdRideSlugs.push(slug);
|
||||
}
|
||||
summary.rides++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,6 +129,23 @@ serve(async (req) => {
|
||||
)
|
||||
}
|
||||
|
||||
// Validate imageId format - Cloudflare accepts UUIDs and alphanumeric IDs
|
||||
// Allow: alphanumeric, hyphens, underscores (common ID formats)
|
||||
// Reject: special characters that could cause injection or path traversal
|
||||
const validImageIdPattern = /^[a-zA-Z0-9_-]{1,100}$/;
|
||||
if (!validImageIdPattern.test(imageId)) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
error: 'Invalid imageId format',
|
||||
message: 'imageId must be alphanumeric with optional hyphens/underscores (max 100 chars)'
|
||||
}),
|
||||
{
|
||||
status: 400,
|
||||
headers: { ...corsHeaders, 'Content-Type': 'application/json' }
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
let deleteResponse;
|
||||
try {
|
||||
deleteResponse = await fetch(
|
||||
|
||||
Reference in New Issue
Block a user