mirror of
https://github.com/pacnpal/thrilltrack-explorer.git
synced 2025-12-20 08:11:13 -05:00
Refactor security policies
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
$$;
|
||||||
Reference in New Issue
Block a user