From 20f3844a582626a6fc11af22aa6b931a6fb6d88a Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Thu, 6 Nov 2025 01:44:28 +0000 Subject: [PATCH] Fix composite submission location --- src/lib/entitySubmissionHelpers.ts | 17 ++ ...5_12955f72-c15d-4c0b-a0a4-fec17858b89c.sql | 245 ++++++++++++++++++ 2 files changed, 262 insertions(+) create mode 100644 supabase/migrations/20251106014355_12955f72-c15d-4c0b-a0a4-fec17858b89c.sql diff --git a/src/lib/entitySubmissionHelpers.ts b/src/lib/entitySubmissionHelpers.ts index 6793164d..713f90be 100644 --- a/src/lib/entitySubmissionHelpers.ts +++ b/src/lib/entitySubmissionHelpers.ts @@ -347,6 +347,23 @@ async function submitCompositeCreation( images: primaryImages as unknown as Json }; + // Convert location object to temp_location_data for parks + if (uploadedPrimary.type === 'park' && uploadedPrimary.data.location) { + primaryData.temp_location_data = { + name: uploadedPrimary.data.location.name, + city: uploadedPrimary.data.location.city || null, + state_province: uploadedPrimary.data.location.state_province || null, + country: uploadedPrimary.data.location.country, + latitude: uploadedPrimary.data.location.latitude, + longitude: uploadedPrimary.data.location.longitude, + timezone: uploadedPrimary.data.location.timezone || null, + postal_code: uploadedPrimary.data.location.postal_code || null, + display_name: uploadedPrimary.data.location.display_name + }; + delete primaryData.location; // Remove the original location object + console.log('[submitCompositeCreation] Converted location to temp_location_data:', primaryData.temp_location_data); + } + // Map temporary IDs to order indices for foreign keys if (uploadedPrimary.type === 'park') { if (uploadedPrimary.data.operator_id?.startsWith('temp-')) { diff --git a/supabase/migrations/20251106014355_12955f72-c15d-4c0b-a0a4-fec17858b89c.sql b/supabase/migrations/20251106014355_12955f72-c15d-4c0b-a0a4-fec17858b89c.sql new file mode 100644 index 00000000..0d6ff920 --- /dev/null +++ b/supabase/migrations/20251106014355_12955f72-c15d-4c0b-a0a4-fec17858b89c.sql @@ -0,0 +1,245 @@ +-- Fix search_path security warning for create_submission_with_items function +-- Set explicit search_path to prevent search path manipulation attacks + +CREATE OR REPLACE FUNCTION create_submission_with_items( + p_submission_id UUID, + p_entity_type TEXT, + p_action_type TEXT, + p_items JSONB, + p_user_id UUID +) +RETURNS UUID +LANGUAGE plpgsql +SECURITY DEFINER +SET search_path = public +AS $$ +DECLARE + v_item JSONB; + v_item_type TEXT; + v_item_data JSONB; + v_depends_on INTEGER; + v_order_index INTEGER; + v_created_ids UUID[] := ARRAY[]::UUID[]; + v_submission_item_id UUID; +BEGIN + -- Loop through items array + FOR v_item IN SELECT * FROM jsonb_array_elements(p_items) + LOOP + v_item_type := v_item->>'item_type'; + v_item_data := v_item->'item_data'; + v_depends_on := (v_item->>'depends_on')::INTEGER; + v_order_index := (v_item->>'order_index')::INTEGER; + + -- Resolve dependency references + IF v_depends_on IS NOT NULL THEN + v_item_data := v_item_data || jsonb_build_object( + v_item->>'dependency_field', + v_created_ids[v_depends_on + 1] + ); + END IF; + + -- Create submission based on entity type + IF v_item_type = 'park' THEN + INSERT INTO park_submissions ( + id, + user_id, + action_type, + status, + name, + slug, + description, + opening_date, + opening_date_precision, + closing_date, + closing_date_precision, + status_park, + website, + park_type, + operator_id, + property_owner_id, + location_id, + temp_location_data, + images + ) VALUES ( + COALESCE((v_item_data->>'id')::UUID, gen_random_uuid()), + p_user_id, + p_action_type, + 'pending', + v_item_data->>'name', + v_item_data->>'slug', + v_item_data->>'description', + (v_item_data->>'opening_date')::DATE, + v_item_data->>'opening_date_precision', + (v_item_data->>'closing_date')::DATE, + v_item_data->>'closing_date_precision', + v_item_data->>'status_park', + v_item_data->>'website', + v_item_data->>'park_type', + (v_item_data->>'operator_id')::UUID, + (v_item_data->>'property_owner_id')::UUID, + (v_item_data->>'location_id')::UUID, + (v_item_data->'temp_location_data')::JSONB, + (v_item_data->'images')::JSONB + ) + RETURNING id INTO v_submission_item_id; + + ELSIF v_item_type = 'ride' THEN + INSERT INTO ride_submissions ( + id, + user_id, + action_type, + status, + name, + slug, + description, + opening_date, + opening_date_precision, + closing_date, + closing_date_precision, + status_ride, + park_id, + manufacturer_id, + designer_id, + model_id, + images + ) VALUES ( + COALESCE((v_item_data->>'id')::UUID, gen_random_uuid()), + p_user_id, + p_action_type, + 'pending', + v_item_data->>'name', + v_item_data->>'slug', + v_item_data->>'description', + (v_item_data->>'opening_date')::DATE, + v_item_data->>'opening_date_precision', + (v_item_data->>'closing_date')::DATE, + v_item_data->>'closing_date_precision', + v_item_data->>'status_ride', + (v_item_data->>'park_id')::UUID, + (v_item_data->>'manufacturer_id')::UUID, + (v_item_data->>'designer_id')::UUID, + (v_item_data->>'model_id')::UUID, + (v_item_data->'images')::JSONB + ) + RETURNING id INTO v_submission_item_id; + + ELSIF v_item_type = 'operator' THEN + INSERT INTO operator_submissions ( + id, + user_id, + action_type, + status, + name, + slug, + description, + website, + images + ) VALUES ( + COALESCE((v_item_data->>'id')::UUID, gen_random_uuid()), + p_user_id, + p_action_type, + 'pending', + v_item_data->>'name', + v_item_data->>'slug', + v_item_data->>'description', + v_item_data->>'website', + (v_item_data->'images')::JSONB + ) + RETURNING id INTO v_submission_item_id; + + ELSIF v_item_type = 'property_owner' THEN + INSERT INTO property_owner_submissions ( + id, + user_id, + action_type, + status, + name, + slug, + description, + website, + images + ) VALUES ( + COALESCE((v_item_data->>'id')::UUID, gen_random_uuid()), + p_user_id, + p_action_type, + 'pending', + v_item_data->>'name', + v_item_data->>'slug', + v_item_data->>'description', + v_item_data->>'website', + (v_item_data->'images')::JSONB + ) + RETURNING id INTO v_submission_item_id; + + ELSIF v_item_type = 'manufacturer' THEN + INSERT INTO manufacturer_submissions ( + id, + user_id, + action_type, + status, + name, + slug, + description, + website, + images + ) VALUES ( + COALESCE((v_item_data->>'id')::UUID, gen_random_uuid()), + p_user_id, + p_action_type, + 'pending', + v_item_data->>'name', + v_item_data->>'slug', + v_item_data->>'description', + v_item_data->>'website', + (v_item_data->'images')::JSONB + ) + RETURNING id INTO v_submission_item_id; + + ELSIF v_item_type = 'designer' THEN + INSERT INTO designer_submissions ( + id, + user_id, + action_type, + status, + name, + slug, + description, + website, + images + ) VALUES ( + COALESCE((v_item_data->>'id')::UUID, gen_random_uuid()), + p_user_id, + p_action_type, + 'pending', + v_item_data->>'name', + v_item_data->>'slug', + v_item_data->>'description', + v_item_data->>'website', + (v_item_data->'images')::JSONB + ) + RETURNING id INTO v_submission_item_id; + + ELSE + RAISE EXCEPTION 'Unsupported item type: %', v_item_type; + END IF; + + -- Track created IDs in order + v_created_ids := array_append(v_created_ids, v_submission_item_id); + + -- Create submission_items record to link everything + INSERT INTO submission_items ( + submission_id, + item_type, + item_id, + order_index + ) VALUES ( + p_submission_id, + v_item_type, + v_submission_item_id, + v_order_index + ); + END LOOP; + + RETURN p_submission_id; +END; +$$; \ No newline at end of file