From 59024669c4e16cd7575542560994d18ad83598d6 Mon Sep 17 00:00:00 2001 From: Karela King Date: Thu, 29 Jan 2026 13:12:09 +0530 Subject: [PATCH 1/4] fix 181: Admin API Exposed in Client Code --- src/components/CreateConversationModal.tsx | 72 ++++++++++++++-------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/src/components/CreateConversationModal.tsx b/src/components/CreateConversationModal.tsx index 4d91a607..313853aa 100644 --- a/src/components/CreateConversationModal.tsx +++ b/src/components/CreateConversationModal.tsx @@ -1,10 +1,10 @@ import { useState, useEffect } from 'react'; import { useCreateConversation } from '../hooks/useMessaging'; -import { supabase } from '../supabase-client'; +import { supabase, isBackendAvailable } from '../supabase-client'; import { useAuth } from '../hooks/useAuth'; import { X, Search, Users, MessageCircle, Check } from 'lucide-react'; import type { Conversation } from '../types/messaging'; -import { showSuccess,showError } from '../utils/toast'; +import { showSuccess, showError } from '../utils/toast'; interface CreateConversationModalProps { @@ -39,15 +39,35 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve // Fetch users for selection useEffect(() => { const fetchUsers = async () => { + if (!isBackendAvailable || !supabase) { + console.warn('Backend unavailable - cannot fetch users'); + setUsers([]); + return; + } + try { - const { data, error } = await supabase.auth.admin.listUsers(); + // ✅ SECURE: Query profiles table with RLS instead of admin API + const { data, error } = await supabase + .from('Profiles') + .select('id, full_name, avatar_url') + .neq('id', currentUser?.id || ''); + if (error) throw error; - - // Filter out current user - const filteredUsers = data.users.filter(u => u.id !== currentUser?.id); - setUsers(filteredUsers as User[]); + + // Map profiles to User format + const mappedUsers = (data || []).map(profile => ({ + id: profile.id, + email: '', // Email not exposed for privacy + user_metadata: { + full_name: profile.full_name, + avatar_url: profile.avatar_url, + }, + })); + + setUsers(mappedUsers as User[]); } catch (error) { console.error('Failed to fetch users:', error); + showError('Failed to load users'); } }; @@ -60,10 +80,10 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve const fullName = user.user_metadata?.full_name?.toLowerCase() || ''; const userName = user.user_metadata?.user_name?.toLowerCase() || ''; const email = user.email.toLowerCase(); - - return fullName.includes(searchLower) || - userName.includes(searchLower) || - email.includes(searchLower); + + return fullName.includes(searchLower) || + userName.includes(searchLower) || + email.includes(searchLower); }); const handleUserSelect = (user: User) => { @@ -83,14 +103,14 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve const handleCreate = async () => { if (selectedUsers.length === 0) return; - + if (conversationType === 'group' && !groupName.trim()) { showError('Please enter a group name'); return; } setIsLoading(true); - + try { const conversationData = { type: conversationType, @@ -101,12 +121,12 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve }; const conversation = await createConversation.mutateAsync(conversationData); - + showSuccess( - conversationType === 'group' + conversationType === 'group' ? "Group conversation created" - : "Conversation started" - ); + : "Conversation started" + ); onConversationCreated(conversation); @@ -119,9 +139,9 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve }; const getUserDisplayName = (user: User) => { - return user.user_metadata?.full_name || - user.user_metadata?.user_name || - user.email; + return user.user_metadata?.full_name || + user.user_metadata?.user_name || + user.email; }; return ( @@ -196,7 +216,7 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve className="w-full px-3 py-2 bg-slate-800/50 border border-slate-700 rounded-lg text-white placeholder-gray-400 focus:outline-none focus:border-cyan-400/50 focus:ring-1 focus:ring-cyan-400/50" /> - +
- +
{filteredUsers.map(user => { const isSelected = selectedUsers.some(u => u.id === user.id); - + return (
)} - +

{getUserDisplayName(user)}

{user.email}

- + {isSelected && ( )}
); })} - + {filteredUsers.length === 0 && (
No users found From 99c21f163e1729ccffc756fa87b5b7cef94a3002 Mon Sep 17 00:00:00 2001 From: MRADUL KUMAR KATIYAR <87556435+Karelaking@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:25:19 +0530 Subject: [PATCH 2/4] Update src/components/CreateConversationModal.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/CreateConversationModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/CreateConversationModal.tsx b/src/components/CreateConversationModal.tsx index 313853aa..b5dff7ca 100644 --- a/src/components/CreateConversationModal.tsx +++ b/src/components/CreateConversationModal.tsx @@ -48,7 +48,7 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve try { // ✅ SECURE: Query profiles table with RLS instead of admin API const { data, error } = await supabase - .from('Profiles') + .from('profiles') .select('id, full_name, avatar_url') .neq('id', currentUser?.id || ''); From 5faf5c4105f03675748322fbbf8c4555f85d683f Mon Sep 17 00:00:00 2001 From: MRADUL KUMAR KATIYAR <87556435+Karelaking@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:25:29 +0530 Subject: [PATCH 3/4] Update src/components/CreateConversationModal.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/CreateConversationModal.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/components/CreateConversationModal.tsx b/src/components/CreateConversationModal.tsx index b5dff7ca..583f2c71 100644 --- a/src/components/CreateConversationModal.tsx +++ b/src/components/CreateConversationModal.tsx @@ -49,8 +49,7 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve // ✅ SECURE: Query profiles table with RLS instead of admin API const { data, error } = await supabase .from('profiles') - .select('id, full_name, avatar_url') - .neq('id', currentUser?.id || ''); + .select('id, full_name, avatar_url'); if (error) throw error; From bd14c03ff06757be1ce8d9a34a3740f2a975bde3 Mon Sep 17 00:00:00 2001 From: MRADUL KUMAR KATIYAR <87556435+Karelaking@users.noreply.github.com> Date: Thu, 29 Jan 2026 13:25:59 +0530 Subject: [PATCH 4/4] Update src/components/CreateConversationModal.tsx Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/components/CreateConversationModal.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/CreateConversationModal.tsx b/src/components/CreateConversationModal.tsx index 583f2c71..708059ad 100644 --- a/src/components/CreateConversationModal.tsx +++ b/src/components/CreateConversationModal.tsx @@ -140,7 +140,8 @@ const CreateConversationModal = ({ onClose, onConversationCreated }: CreateConve const getUserDisplayName = (user: User) => { return user.user_metadata?.full_name || user.user_metadata?.user_name || - user.email; + user.email || + user.id; }; return (