51 lines
2.7 KiB
PL/PgSQL
51 lines
2.7 KiB
PL/PgSQL
create schema if not exists minegeo_private;
|
|
revoke all on schema minegeo_private from public, anon, authenticated;
|
|
grant usage on schema minegeo_private to service_role;
|
|
|
|
create table minegeo_private.legacy_password_claims (
|
|
user_id uuid primary key references auth.users(id) on delete cascade,
|
|
claimed_at timestamptz not null default now()
|
|
);
|
|
alter table minegeo_private.legacy_password_claims enable row level security;
|
|
revoke all on minegeo_private.legacy_password_claims from public, anon, authenticated;
|
|
grant select, insert on minegeo_private.legacy_password_claims to service_role;
|
|
create policy "Server reads password claims" on minegeo_private.legacy_password_claims
|
|
for select to service_role using (true);
|
|
create policy "Server creates password claims" on minegeo_private.legacy_password_claims
|
|
for insert to service_role with check (true);
|
|
|
|
-- This private helper reads only password eligibility, never returns a hash,
|
|
-- and never stores a plaintext password. Only the trusted server can call it.
|
|
create function minegeo_private.legacy_password(p_user uuid, p_claim boolean)
|
|
returns boolean language plpgsql security definer set search_path = '' as $$
|
|
declare eligible boolean; claimed uuid;
|
|
begin
|
|
if auth.uid() is not null and auth.uid() <> p_user then return false; end if;
|
|
select coalesce(encrypted_password, '') = '' and email is not null
|
|
and email_confirmed_at is not null and not coalesce(is_anonymous, false)
|
|
into eligible from auth.users where id = p_user for update;
|
|
if not coalesce(eligible, false) then return false; end if;
|
|
if not p_claim then
|
|
return not exists(select 1 from minegeo_private.legacy_password_claims where user_id = p_user);
|
|
end if;
|
|
insert into minegeo_private.legacy_password_claims(user_id) values(p_user)
|
|
on conflict(user_id) do nothing returning user_id into claimed;
|
|
return claimed is not null;
|
|
end;
|
|
$$;
|
|
revoke all on function minegeo_private.legacy_password(uuid,boolean) from public, anon, authenticated;
|
|
grant execute on function minegeo_private.legacy_password(uuid,boolean) to service_role;
|
|
|
|
create function public.legacy_password_needed(p_user uuid)
|
|
returns boolean language sql security invoker set search_path = '' as $$
|
|
select minegeo_private.legacy_password(p_user, false);
|
|
$$;
|
|
create function public.claim_legacy_password(p_user uuid)
|
|
returns boolean language sql security invoker set search_path = '' as $$
|
|
select minegeo_private.legacy_password(p_user, true);
|
|
$$;
|
|
revoke all on function public.legacy_password_needed(uuid) from public, anon, authenticated;
|
|
revoke all on function public.claim_legacy_password(uuid) from public, anon, authenticated;
|
|
grant execute on function public.legacy_password_needed(uuid) to service_role;
|
|
grant execute on function public.claim_legacy_password(uuid) to service_role;
|