From 16ddae1070c324f7ac2917355f372b2a2b4ed183 Mon Sep 17 00:00:00 2001 From: "gpt-engineer-app[bot]" <159125892+gpt-engineer-app[bot]@users.noreply.github.com> Date: Mon, 29 Sep 2025 02:46:42 +0000 Subject: [PATCH] Refactor: Improve profile privacy controls --- ...2_029eb4d5-231b-4d0f-a4f0-1d0b89fc1f44.sql | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 supabase/migrations/20250929024612_029eb4d5-231b-4d0f-a4f0-1d0b89fc1f44.sql diff --git a/supabase/migrations/20250929024612_029eb4d5-231b-4d0f-a4f0-1d0b89fc1f44.sql b/supabase/migrations/20250929024612_029eb4d5-231b-4d0f-a4f0-1d0b89fc1f44.sql new file mode 100644 index 00000000..ef66e12b --- /dev/null +++ b/supabase/migrations/20250929024612_029eb4d5-231b-4d0f-a4f0-1d0b89fc1f44.sql @@ -0,0 +1,89 @@ +-- Update the can_view_profile_field function to handle all the new privacy settings +CREATE OR REPLACE FUNCTION public.can_view_profile_field(_viewer_id uuid, _profile_user_id uuid, _field_name text) +RETURNS boolean +LANGUAGE plpgsql +STABLE SECURITY DEFINER +SET search_path = 'public' +AS $$ +DECLARE + profile_privacy_level text; + user_privacy_settings jsonb; +BEGIN + -- Allow users to view their own profile fields + IF _viewer_id = _profile_user_id THEN + RETURN true; + END IF; + + -- Allow moderators/admins to view all profile fields + IF is_moderator(_viewer_id) THEN + RETURN true; + END IF; + + -- Get profile privacy level + SELECT privacy_level INTO profile_privacy_level + FROM public.profiles + WHERE user_id = _profile_user_id; + + -- If profile is private, deny access to all fields except basic info + IF profile_privacy_level = 'private' THEN + -- Only allow basic public info for private profiles + RETURN _field_name IN ('username', 'display_name'); + END IF; + + -- For public profiles, check granular privacy settings + SELECT privacy_settings INTO user_privacy_settings + FROM public.user_preferences + WHERE user_id = _profile_user_id; + + -- If no privacy settings found, apply conservative defaults + IF user_privacy_settings IS NULL THEN + -- Only allow basic safe fields + RETURN _field_name IN ('username', 'display_name', 'bio', 'avatar_url', 'show_pronouns', 'preferred_pronouns'); + END IF; + + -- Check specific field permissions based on privacy settings + CASE _field_name + -- Age/birth date fields + WHEN 'date_of_birth' THEN + RETURN COALESCE((user_privacy_settings->>'show_age')::boolean, false); + + -- Location fields + WHEN 'personal_location' THEN + RETURN COALESCE((user_privacy_settings->>'show_location')::boolean, false); + WHEN 'location_id' THEN + RETURN COALESCE((user_privacy_settings->>'show_location')::boolean, false); + + -- Avatar fields + WHEN 'avatar_url', 'avatar_image_id' THEN + RETURN COALESCE((user_privacy_settings->>'show_avatar')::boolean, true); + + -- Bio field + WHEN 'bio' THEN + RETURN COALESCE((user_privacy_settings->>'show_bio')::boolean, true); + + -- Home park field + WHEN 'home_park_id' THEN + RETURN COALESCE((user_privacy_settings->>'show_home_park')::boolean, false); + + -- Activity statistics fields + WHEN 'ride_count', 'coaster_count', 'park_count', 'review_count', 'reputation_score' THEN + RETURN COALESCE((user_privacy_settings->>'show_activity_stats')::boolean, true); + + -- Always allow these basic fields for public profiles + WHEN 'username', 'display_name' THEN + RETURN true; + + -- Respect show_pronouns setting on the profile + WHEN 'preferred_pronouns' THEN + RETURN COALESCE((SELECT show_pronouns FROM public.profiles WHERE user_id = _profile_user_id), false); + + -- Allow these safe metadata fields by default + WHEN 'timezone', 'preferred_language', 'theme_preference', 'privacy_level', 'show_pronouns', 'created_at', 'updated_at' THEN + RETURN true; + + -- Deny access to other sensitive fields by default + ELSE + RETURN false; + END CASE; +END; +$$; \ No newline at end of file