mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 10:31:13 -05:00
205 lines
8.2 KiB
PL/PgSQL
205 lines
8.2 KiB
PL/PgSQL
-- Drop the broken JSONB-based rollback function
|
|
DROP FUNCTION IF EXISTS public.rollback_to_version(TEXT, UUID, UUID, UUID, TEXT);
|
|
|
|
-- Create new relational rollback function with moderator-only access
|
|
CREATE OR REPLACE FUNCTION public.rollback_to_version(
|
|
p_entity_type TEXT,
|
|
p_entity_id UUID,
|
|
p_target_version_id UUID,
|
|
p_changed_by UUID,
|
|
p_reason TEXT
|
|
)
|
|
RETURNS UUID
|
|
LANGUAGE plpgsql
|
|
SECURITY DEFINER
|
|
SET search_path = 'public'
|
|
AS $$
|
|
DECLARE
|
|
v_version_table TEXT;
|
|
v_entity_table TEXT;
|
|
v_entity_id_col TEXT;
|
|
v_new_version_id UUID;
|
|
v_version_data RECORD;
|
|
BEGIN
|
|
-- CRITICAL: Check authorization FIRST
|
|
IF NOT is_moderator(p_changed_by) THEN
|
|
RAISE EXCEPTION 'Only moderators can rollback versions'
|
|
USING ERRCODE = '42501'; -- insufficient_privilege
|
|
END IF;
|
|
|
|
-- Validate entity type
|
|
IF p_entity_type NOT IN ('park', 'ride', 'company', 'ride_model') THEN
|
|
RAISE EXCEPTION 'Invalid entity type: %', p_entity_type;
|
|
END IF;
|
|
|
|
-- Determine table names
|
|
v_version_table := p_entity_type || '_versions';
|
|
v_entity_id_col := p_entity_type || '_id';
|
|
v_entity_table := CASE p_entity_type
|
|
WHEN 'park' THEN 'parks'
|
|
WHEN 'ride' THEN 'rides'
|
|
WHEN 'company' THEN 'companies'
|
|
WHEN 'ride_model' THEN 'ride_models'
|
|
END;
|
|
|
|
-- Get the target version data
|
|
EXECUTE format('SELECT * FROM %I WHERE version_id = $1', v_version_table)
|
|
INTO v_version_data
|
|
USING p_target_version_id;
|
|
|
|
IF v_version_data IS NULL THEN
|
|
RAISE EXCEPTION 'Version not found: %', p_target_version_id;
|
|
END IF;
|
|
|
|
-- Set session variables for trigger
|
|
PERFORM set_config('app.current_user_id', p_changed_by::text, true);
|
|
PERFORM set_config('app.submission_id', '', true);
|
|
|
|
-- Restore entity data based on type
|
|
IF p_entity_type = 'park' THEN
|
|
UPDATE parks SET
|
|
name = v_version_data.name,
|
|
slug = v_version_data.slug,
|
|
description = v_version_data.description,
|
|
park_type = v_version_data.park_type,
|
|
status = v_version_data.status,
|
|
location_id = v_version_data.location_id,
|
|
operator_id = v_version_data.operator_id,
|
|
property_owner_id = v_version_data.property_owner_id,
|
|
opening_date = v_version_data.opening_date,
|
|
closing_date = v_version_data.closing_date,
|
|
opening_date_precision = v_version_data.opening_date_precision,
|
|
closing_date_precision = v_version_data.closing_date_precision,
|
|
website_url = v_version_data.website_url,
|
|
phone = v_version_data.phone,
|
|
email = v_version_data.email,
|
|
banner_image_url = v_version_data.banner_image_url,
|
|
banner_image_id = v_version_data.banner_image_id,
|
|
card_image_url = v_version_data.card_image_url,
|
|
card_image_id = v_version_data.card_image_id,
|
|
updated_at = NOW()
|
|
WHERE id = p_entity_id;
|
|
|
|
ELSIF p_entity_type = 'ride' THEN
|
|
UPDATE rides SET
|
|
name = v_version_data.name,
|
|
slug = v_version_data.slug,
|
|
description = v_version_data.description,
|
|
category = v_version_data.category,
|
|
status = v_version_data.status,
|
|
park_id = v_version_data.park_id,
|
|
manufacturer_id = v_version_data.manufacturer_id,
|
|
designer_id = v_version_data.designer_id,
|
|
ride_model_id = v_version_data.ride_model_id,
|
|
opening_date = v_version_data.opening_date,
|
|
closing_date = v_version_data.closing_date,
|
|
opening_date_precision = v_version_data.opening_date_precision,
|
|
closing_date_precision = v_version_data.closing_date_precision,
|
|
height_requirement = v_version_data.height_requirement_cm,
|
|
age_requirement = v_version_data.age_requirement,
|
|
max_speed_kmh = v_version_data.max_speed_kmh,
|
|
duration_seconds = v_version_data.duration_seconds,
|
|
capacity_per_hour = v_version_data.capacity_per_hour,
|
|
max_g_force = v_version_data.gforce_max,
|
|
inversions = v_version_data.inversions_count,
|
|
length_meters = v_version_data.length_meters,
|
|
max_height_meters = v_version_data.height_meters,
|
|
drop_height_meters = v_version_data.drop_meters,
|
|
banner_image_url = v_version_data.banner_image_url,
|
|
banner_image_id = v_version_data.banner_image_id,
|
|
card_image_url = v_version_data.card_image_url,
|
|
card_image_id = v_version_data.card_image_id,
|
|
image_url = v_version_data.image_url,
|
|
ride_sub_type = v_version_data.ride_sub_type,
|
|
coaster_type = v_version_data.coaster_type,
|
|
seating_type = v_version_data.seating_type,
|
|
intensity_level = v_version_data.intensity_level,
|
|
track_material = v_version_data.track_material,
|
|
support_material = v_version_data.support_material,
|
|
propulsion_method = v_version_data.propulsion_method,
|
|
water_depth_cm = v_version_data.water_depth_cm,
|
|
splash_height_meters = v_version_data.splash_height_meters,
|
|
wetness_level = v_version_data.wetness_level,
|
|
flume_type = v_version_data.flume_type,
|
|
boat_capacity = v_version_data.boat_capacity,
|
|
theme_name = v_version_data.theme_name,
|
|
story_description = v_version_data.story_description,
|
|
show_duration_seconds = v_version_data.show_duration_seconds,
|
|
animatronics_count = v_version_data.animatronics_count,
|
|
projection_type = v_version_data.projection_type,
|
|
ride_system = v_version_data.ride_system,
|
|
scenes_count = v_version_data.scenes_count,
|
|
rotation_type = v_version_data.rotation_type,
|
|
motion_pattern = v_version_data.motion_pattern,
|
|
platform_count = v_version_data.platform_count,
|
|
swing_angle_degrees = v_version_data.swing_angle_degrees,
|
|
rotation_speed_rpm = v_version_data.rotation_speed_rpm,
|
|
arm_length_meters = v_version_data.arm_length_meters,
|
|
max_height_reached_meters = v_version_data.max_height_reached_meters,
|
|
min_age = v_version_data.min_age,
|
|
max_age = v_version_data.max_age,
|
|
educational_theme = v_version_data.educational_theme,
|
|
character_theme = v_version_data.character_theme,
|
|
transport_type = v_version_data.transport_type,
|
|
route_length_meters = v_version_data.route_length_meters,
|
|
stations_count = v_version_data.stations_count,
|
|
vehicle_capacity = v_version_data.vehicle_capacity,
|
|
vehicles_count = v_version_data.vehicles_count,
|
|
round_trip_duration_seconds = v_version_data.round_trip_duration_seconds,
|
|
updated_at = NOW()
|
|
WHERE id = p_entity_id;
|
|
|
|
ELSIF p_entity_type = 'company' THEN
|
|
UPDATE companies SET
|
|
name = v_version_data.name,
|
|
slug = v_version_data.slug,
|
|
description = v_version_data.description,
|
|
company_type = v_version_data.company_type,
|
|
person_type = v_version_data.person_type,
|
|
founded_year = v_version_data.founded_year,
|
|
founded_date = v_version_data.founded_date,
|
|
founded_date_precision = v_version_data.founded_date_precision,
|
|
headquarters_location = v_version_data.headquarters_location,
|
|
website_url = v_version_data.website_url,
|
|
logo_url = v_version_data.logo_url,
|
|
banner_image_url = v_version_data.banner_image_url,
|
|
banner_image_id = v_version_data.banner_image_id,
|
|
card_image_url = v_version_data.card_image_url,
|
|
card_image_id = v_version_data.card_image_id,
|
|
updated_at = NOW()
|
|
WHERE id = p_entity_id;
|
|
|
|
ELSIF p_entity_type = 'ride_model' THEN
|
|
UPDATE ride_models SET
|
|
name = v_version_data.name,
|
|
slug = v_version_data.slug,
|
|
manufacturer_id = v_version_data.manufacturer_id,
|
|
category = v_version_data.category,
|
|
ride_type = v_version_data.ride_type,
|
|
description = v_version_data.description,
|
|
banner_image_url = v_version_data.banner_image_url,
|
|
banner_image_id = v_version_data.banner_image_id,
|
|
card_image_url = v_version_data.card_image_url,
|
|
card_image_id = v_version_data.card_image_id,
|
|
updated_at = NOW()
|
|
WHERE id = p_entity_id;
|
|
END IF;
|
|
|
|
-- Update the newly created version with restored change type and reason
|
|
EXECUTE format('
|
|
UPDATE %I
|
|
SET
|
|
change_type = $1,
|
|
change_reason = $2
|
|
WHERE %I = $3
|
|
AND is_current = true
|
|
RETURNING version_id
|
|
', v_version_table, v_entity_id_col)
|
|
INTO v_new_version_id
|
|
USING 'restored'::version_change_type,
|
|
'Restored to version ' || v_version_data.version_number || ': ' || p_reason,
|
|
p_entity_id;
|
|
|
|
RETURN v_new_version_id;
|
|
END;
|
|
$$; |