Skip to content

Commit

Permalink
fix(supabase): Update tag search by phone
Browse files Browse the repository at this point in the history
Previously, searching by phone worked for all profiles. Now, only public profiles are returned in the matches.
  • Loading branch information
0xBigBoss committed Dec 23, 2024
1 parent f3149c2 commit 41ac405
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
set check_function_bodies = off;

CREATE OR REPLACE FUNCTION public.tag_search(query text, limit_val integer, offset_val integer)
RETURNS TABLE(send_id_matches tag_search_result[], tag_matches tag_search_result[], phone_matches tag_search_result[])
LANGUAGE plpgsql
IMMUTABLE SECURITY DEFINER
AS $function$
begin
if limit_val is null or (limit_val <= 0 or limit_val > 100) then
raise exception 'limit_val must be between 1 and 100';
end if;
if offset_val is null or offset_val < 0 then
raise exception 'offset_val must be greater than or equal to 0';
end if;
return query --
select ( select array_agg(row (sub.avatar_url, sub.tag_name, sub.send_id, sub.phone)::public.tag_search_result)
from ( select p.avatar_url, t.name as tag_name, p.send_id, null::text as phone
from profiles p
left join tags t on t.user_id = p.id and t.status = 'confirmed'
where query similar to '\d+'
and p.send_id::varchar like '%' || query || '%'
order by p.send_id
limit limit_val offset offset_val ) sub ) as send_id_matches,
( select array_agg(row (sub.avatar_url, sub.tag_name, sub.send_id, sub.phone)::public.tag_search_result)
from ( select p.avatar_url, t.name as tag_name, p.send_id, null::text as phone
from profiles p
join tags t on t.user_id = p.id
where t.status = 'confirmed'
and (t.name <<-> query < 0.7 or t.name ilike '%' || query || '%')
order by (t.name <-> query)
limit limit_val offset offset_val ) sub ) as tag_matches,
( select array_agg(row (sub.avatar_url, sub.tag_name, sub.send_id, sub.phone)::public.tag_search_result)
from ( select p.avatar_url, t.name as tag_name, p.send_id, u.phone
from profiles p
left join tags t on t.user_id = p.id and t.status = 'confirmed'
join auth.users u on u.id = p.id
where p.is_public
and query ~ '^\d{8,}$'
and u.phone like query || '%'
order by u.phone
limit limit_val offset offset_val ) sub ) as phone_matches;
end;
$function$
;

revoke all on function public.tag_search(q text, limit_val int, offset_val int) from anon;
32 changes: 31 additions & 1 deletion supabase/tests/tags_search_test.sql
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- Tag Search
begin;

select plan(6);
select plan(8);

create extension "basejump-supabase_test_helpers"; -- noqa: RF05

Expand Down Expand Up @@ -99,5 +99,35 @@ select results_eq($$
)::tag_search_result]
) $$, 'You can search by send_id');

-- Test phone number privacy
select tests.authenticate_as_service_role();
-- Make Bob's profile private
update profiles set is_public = false where id = tests.get_supabase_uid('bob');

select tests.authenticate_as('neo');

-- Verify that private profile phone numbers are not searchable
select results_eq($$
SELECT coalesce(array_length(phone_matches,1), 0) from tag_search( $$ || :bobs_phone_number || $$::text, 1, 0); $$, $$
values (0) $$, 'Private profile phone numbers should not be searchable');

-- Make Bob's profile public again
select tests.authenticate_as_service_role();
update profiles set is_public = true where id = tests.get_supabase_uid('bob');

select tests.authenticate_as('neo');

-- Verify that public profile phone numbers are searchable
select results_eq($$
SELECT phone_matches from tag_search( $$ || :bobs_phone_number || $$::text, 1, 0); $$, $$
values (
ARRAY[ROW(
'bob_avatar', -- avatar_url
null, -- tag_name
$$ || :bob_send_id || $$, -- bob's send_id
$$ || :bobs_phone_number || $$ -- bob's phone number
)::tag_search_result]
) $$, 'Public profile phone numbers should be searchable');

select finish();
rollback;

0 comments on commit 41ac405

Please sign in to comment.