sipher/supabase/user_management_functions.sql
Nyxian 79bdca973c UI+ Routes
Made even more changes the UI and added new Routes for searching a user, requesting consent for messaging and others.
Now just need to make the SSE work.
2024-12-12 08:56:11 -03:00

116 lines
3.1 KiB
PL/PgSQL

-- For generate_short_uuid
CREATE
OR REPLACE FUNCTION public.generate_short_uuid () RETURNS TEXT AS $$
DECLARE
chars TEXT := 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
result TEXT := '';
i INTEGER := 0;
max_attempts INTEGER := 10;
current_attempt INTEGER := 0;
is_unique BOOLEAN := false;
BEGIN
WHILE NOT is_unique AND current_attempt < max_attempts LOOP
result := '';
FOR i IN 1..8 LOOP
result := result || substr(chars, floor(random() * length(chars) + 1)::integer, 1);
END LOOP;
SELECT COUNT(*) = 0 INTO is_unique
FROM public.users
WHERE suuid = result;
current_attempt := current_attempt + 1;
END LOOP;
IF NOT is_unique THEN
RAISE EXCEPTION 'Could not generate unique short UUID after % attempts', max_attempts;
END IF;
RETURN result;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION public.search_users(search_term TEXT)
RETURNS TABLE (
uuid UUID,
suuid TEXT,
username TEXT,
indexable BOOLEAN
) AS $$
BEGIN
RETURN QUERY
SELECT
u.uuid,
u.suuid::TEXT,
-- Simplified CASE logic: show username if SUUID match OR (username match AND indexable)
CASE
WHEN u.suuid = search_term OR u.indexable THEN u.username
ELSE NULL
END,
u.indexable
FROM public.users u
WHERE
u.suuid = search_term -- Case 1: SUUID match (always show)
OR (
u.indexable = true AND -- Case 2: Username match + indexable
u.username ILIKE '%' || search_term || '%'
);
END;
$$ LANGUAGE plpgsql;
-- For is_thread_participant
CREATE
OR REPLACE FUNCTION public.is_thread_participant (thread_uuid UUID) RETURNS BOOLEAN AS $$
BEGIN
RETURN EXISTS (
SELECT 1
FROM public.thread_participants
WHERE thread_id = thread_uuid
AND user_uuid = auth.uid()
);
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
-- For get_user_threads
CREATE
OR REPLACE FUNCTION public.get_user_threads (user_id UUID) RETURNS TABLE (
thread_id UUID,
participants TEXT[],
messages JSON[]
) AS $$
BEGIN
IF NOT EXISTS (
SELECT 1
FROM public.thread_participants
WHERE user_uuid = user_id
) THEN
-- Return empty result if user has no threads
RETURN;
END IF;
RETURN QUERY
SELECT
mt.id,
array_agg(DISTINCT u.username),
COALESCE(array_agg(
CASE WHEN m.id IS NOT NULL THEN
json_build_object(
'id', m.id,
'content', m.content,
'created_at', m.created_at
)
ELSE NULL END
) FILTER (WHERE m.id IS NOT NULL), ARRAY[]::JSON[])
FROM public.message_threads mt
JOIN public.thread_participants tp ON mt.id = tp.thread_id
JOIN public.users u ON tp.user_uuid = u.uuid
LEFT JOIN public.messages m ON mt.id = m.thread_id
WHERE mt.id IN (
SELECT thread_id
FROM public.thread_participants
WHERE user_uuid = user_id
)
GROUP BY mt.id;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;