Files
thrilltrack-explorer/supabase/migrations/20251012140606_f47fc137-13d2-4cfa-94d3-971f41b77258.sql
2025-10-12 14:06:39 +00:00

83 lines
3.8 KiB
SQL

-- Drop and recreate filtered_profiles view without SECURITY DEFINER
-- This view applies field-level privacy using security definer functions
-- but the view itself should NOT be security definer
DROP VIEW IF EXISTS public.filtered_profiles;
CREATE VIEW public.filtered_profiles AS
SELECT
p.id,
p.user_id,
p.username,
p.display_name,
p.privacy_level,
p.created_at,
p.updated_at,
-- Field-level privacy using security definer functions
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'bio') THEN p.bio
ELSE NULL
END AS bio,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'avatar_url') THEN p.avatar_url
ELSE NULL
END AS avatar_url,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'avatar_image_id') THEN p.avatar_image_id
ELSE NULL
END AS avatar_image_id,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'preferred_pronouns') THEN p.preferred_pronouns
ELSE NULL
END AS preferred_pronouns,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'preferred_pronouns') THEN p.show_pronouns
ELSE false
END AS show_pronouns,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'personal_location') THEN p.personal_location
ELSE NULL
END AS personal_location,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'location_id') THEN p.location_id
ELSE NULL
END AS location_id,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'home_park_id') THEN p.home_park_id
ELSE NULL
END AS home_park_id,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'date_of_birth') THEN p.date_of_birth
ELSE NULL
END AS date_of_birth,
p.timezone,
p.preferred_language,
p.theme_preference,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'ride_count') THEN p.ride_count
ELSE 0
END AS ride_count,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'ride_count') THEN p.coaster_count
ELSE 0
END AS coaster_count,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'ride_count') THEN p.park_count
ELSE 0
END AS park_count,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'ride_count') THEN p.review_count
ELSE 0
END AS review_count,
CASE
WHEN can_view_profile_field(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid), p.user_id, 'ride_count') THEN p.reputation_score
ELSE 0
END AS reputation_score,
CASE
WHEN auth.uid() = p.user_id OR is_moderator(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid)) THEN p.banned
ELSE false
END AS banned
FROM public.profiles p
WHERE (NOT p.banned OR auth.uid() = p.user_id OR is_moderator(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid)))
AND (p.privacy_level = 'public' OR auth.uid() = p.user_id OR is_moderator(COALESCE(auth.uid(), '00000000-0000-0000-0000-000000000000'::uuid)));
COMMENT ON VIEW public.filtered_profiles IS 'Profile view with field-level privacy controls. Uses security definer functions for permission checks but view itself respects querying user context.';