-- Fix user_preferences privacy exposure -- Drop the overly permissive policy DROP POLICY IF EXISTS "Allow reading privacy settings for permission checks" ON public.user_preferences; -- Create a restricted policy: users can only read their own preferences CREATE POLICY "Users can read their own preferences" ON public.user_preferences FOR SELECT TO authenticated USING (auth.uid() = user_id); -- Create a policy for moderators to read all preferences CREATE POLICY "Moderators can read all preferences" ON public.user_preferences FOR SELECT TO authenticated USING (is_moderator(auth.uid())); -- Create a security definer function to check if a user's location should be visible CREATE OR REPLACE FUNCTION public.can_view_user_location(_viewer_id uuid, _profile_user_id uuid) RETURNS boolean LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path = public AS $$ DECLARE user_privacy_settings jsonb; BEGIN -- Always allow users to view their own location IF _viewer_id = _profile_user_id THEN RETURN true; END IF; -- Allow moderators to view all locations IF is_moderator(_viewer_id) THEN RETURN true; END IF; -- Check the user's privacy settings SELECT privacy_settings INTO user_privacy_settings FROM public.user_preferences WHERE user_id = _profile_user_id; -- If no privacy settings found, default to not showing location IF user_privacy_settings IS NULL THEN RETURN false; END IF; -- Check if the user has enabled location visibility RETURN COALESCE((user_privacy_settings->>'show_location')::boolean, false); END; $$;