Skip to content

Commit

Permalink
fix(supabase): Update tag search by phone (#968)
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 authored Dec 23, 2024
1 parent f3149c2 commit 5f64903
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 5f64903

Please sign in to comment.