101 lines
3.0 KiB
PL/PgSQL
101 lines
3.0 KiB
PL/PgSQL
-- Guest access still uses a real authenticated Supabase user. This keeps the
|
|
-- existing ownership checks, RLS policies, and multiplayer membership model.
|
|
-- Email accounts remain restricted to the allowlist.
|
|
|
|
create or replace function public.create_profile_for_allowlisted_user()
|
|
returns trigger
|
|
language plpgsql
|
|
security definer
|
|
set search_path = ''
|
|
as $$
|
|
declare
|
|
v_is_anonymous boolean := coalesce(new.is_anonymous, false);
|
|
v_display_name text;
|
|
begin
|
|
if not v_is_anonymous and (
|
|
new.email is null or not exists (
|
|
select 1
|
|
from public.allowlist
|
|
where email = lower(btrim(new.email))
|
|
)
|
|
) then
|
|
raise exception using
|
|
errcode = '42501',
|
|
message = 'This email is not invited to the Dungeons & Ground alpha.';
|
|
end if;
|
|
|
|
v_display_name := case
|
|
when v_is_anonymous then 'Guest ' || upper(substr(replace(new.id::text, '-', ''), 1, 6))
|
|
else coalesce(nullif(btrim(new.raw_user_meta_data ->> 'display_name'), ''), 'Adventurer')
|
|
end;
|
|
|
|
insert into public.profiles(id, display_name)
|
|
values (new.id, v_display_name)
|
|
on conflict (id) do nothing;
|
|
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.create_profile_for_allowlisted_user() from public;
|
|
|
|
-- An anonymous account can be upgraded later. Recheck the allowlist on the
|
|
-- relevant auth.users transition so linking an email cannot bypass the alpha
|
|
-- gate. Unrelated token and metadata updates do not fire this trigger.
|
|
create or replace function public.enforce_alpha_email_allowlist()
|
|
returns trigger
|
|
language plpgsql
|
|
security definer
|
|
set search_path = ''
|
|
as $$
|
|
begin
|
|
if not coalesce(new.is_anonymous, false) and (
|
|
new.email is null or not exists (
|
|
select 1
|
|
from public.allowlist
|
|
where email = lower(btrim(new.email))
|
|
)
|
|
) then
|
|
raise exception using
|
|
errcode = '42501',
|
|
message = 'This email is not invited to the Dungeons & Ground alpha.';
|
|
end if;
|
|
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.enforce_alpha_email_allowlist() from public;
|
|
|
|
drop trigger if exists enforce_alpha_email_allowlist on auth.users;
|
|
create trigger enforce_alpha_email_allowlist
|
|
before update of email, is_anonymous on auth.users
|
|
for each row
|
|
when (
|
|
old.email is distinct from new.email
|
|
or old.is_anonymous is distinct from new.is_anonymous
|
|
)
|
|
execute function public.enforce_alpha_email_allowlist();
|
|
|
|
-- The schema may be installed after Auth users already exist. Backfill only
|
|
-- anonymous users and explicitly allowlisted email accounts; do not silently
|
|
-- enable unrelated accounts.
|
|
insert into public.profiles(id, display_name)
|
|
select
|
|
auth_user.id,
|
|
case
|
|
when coalesce(auth_user.is_anonymous, false)
|
|
then 'Guest ' || upper(substr(replace(auth_user.id::text, '-', ''), 1, 6))
|
|
else coalesce(nullif(btrim(auth_user.raw_user_meta_data ->> 'display_name'), ''), 'Adventurer')
|
|
end
|
|
from auth.users auth_user
|
|
where coalesce(auth_user.is_anonymous, false)
|
|
or exists (
|
|
select 1
|
|
from public.allowlist
|
|
where allowlist.email = lower(btrim(auth_user.email))
|
|
)
|
|
on conflict (id) do nothing;
|
|
|
|
notify pgrst, 'reload schema';
|