Refactor security policies

This commit is contained in:
gpt-engineer-app[bot]
2025-09-29 22:19:22 +00:00
parent f586b31954
commit 622c9ba064
4 changed files with 88 additions and 29 deletions

View File

@@ -19,25 +19,26 @@ export function LocationDisplay({ location, userId, isOwnProfile }: LocationDisp
}, [userId, isOwnProfile]); }, [userId, isOwnProfile]);
const fetchLocationPrivacy = async () => { const fetchLocationPrivacy = async () => {
// Always show location for own profile
if (isOwnProfile) {
setShowLocation(true);
return;
}
try { try {
const { data } = await supabase const { data: { user } } = await supabase.auth.getUser();
.from('user_preferences') const viewerId = user?.id;
.select('privacy_settings')
.eq('user_id', userId)
.maybeSingle();
if (data?.privacy_settings) { // Use the secure function to check location visibility
const settings = data.privacy_settings as any; const { data, error } = await supabase
setShowLocation(settings.show_location || false); .rpc('can_view_user_location', {
_viewer_id: viewerId,
_profile_user_id: userId
});
if (error) {
console.error('Error checking location privacy:', error);
setShowLocation(false);
return;
} }
setShowLocation(data || false);
} catch (error) { } catch (error) {
console.error('Error fetching location privacy:', error); console.error('Error checking location privacy:', error);
setShowLocation(false); setShowLocation(false);
} }
}; };

View File

@@ -16,23 +16,24 @@ export function PersonalLocationDisplay({ personalLocation, userId, isOwnProfile
}, [userId, isOwnProfile]); }, [userId, isOwnProfile]);
const fetchLocationPrivacy = async () => { const fetchLocationPrivacy = async () => {
// Always show location for own profile
if (isOwnProfile) {
setShowLocation(true);
return;
}
try { try {
const { data } = await supabase const { data: { user } } = await supabase.auth.getUser();
.from('user_preferences') const viewerId = user?.id;
.select('privacy_settings')
.eq('user_id', userId)
.maybeSingle();
if (data?.privacy_settings) { // Use the secure function to check location visibility
const settings = data.privacy_settings as any; const { data, error } = await supabase
setShowLocation(settings.show_location || false); .rpc('can_view_user_location', {
_viewer_id: viewerId,
_profile_user_id: userId
});
if (error) {
console.error('Error checking location privacy:', error);
setShowLocation(false);
return;
} }
setShowLocation(data || false);
} catch (error) { } catch (error) {
console.error('Error fetching location privacy:', error); console.error('Error fetching location privacy:', error);
setShowLocation(false); setShowLocation(false);

View File

@@ -964,6 +964,10 @@ export type Database = {
} }
Returns: boolean Returns: boolean
} }
can_view_user_location: {
Args: { _profile_user_id: string; _viewer_id: string }
Returns: boolean
}
get_user_management_permissions: { get_user_management_permissions: {
Args: { _user_id: string } Args: { _user_id: string }
Returns: Json Returns: Json

View File

@@ -0,0 +1,53 @@
-- 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;
$$;