540b506f91
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
68 lines
2.0 KiB
PL/PgSQL
68 lines
2.0 KiB
PL/PgSQL
-- Phase 3: per-device revocation. Adds a revoked_at flag, an RPC that lets
|
|
-- the device's owner flip it, and publishes the devices table to realtime
|
|
-- so every signed-in install can react to its own row being revoked.
|
|
|
|
alter table public.devices
|
|
add column if not exists revoked_at timestamptz null;
|
|
|
|
create index if not exists devices_user_revoked_idx
|
|
on public.devices(user_id, revoked_at);
|
|
|
|
-- RLS: existing policy on devices already gates by user_id; an UPDATE done
|
|
-- via the RPC runs with SECURITY DEFINER so we don't widen the RLS surface.
|
|
|
|
create or replace function public.revoke_device(p_device_id uuid)
|
|
returns void
|
|
language plpgsql
|
|
security definer
|
|
set search_path = public
|
|
as $$
|
|
declare
|
|
v_owner uuid;
|
|
begin
|
|
if auth.uid() is null then
|
|
raise exception 'not authenticated' using errcode = '28000';
|
|
end if;
|
|
|
|
select user_id into v_owner
|
|
from public.devices
|
|
where id = p_device_id;
|
|
|
|
if v_owner is null then
|
|
raise exception 'device not found' using errcode = 'P0002';
|
|
end if;
|
|
|
|
if v_owner <> auth.uid() then
|
|
raise exception 'not authorized' using errcode = '42501';
|
|
end if;
|
|
|
|
update public.devices
|
|
set revoked_at = now()
|
|
where id = p_device_id
|
|
and revoked_at is null;
|
|
end;
|
|
$$;
|
|
|
|
revoke all on function public.revoke_device(uuid) from public;
|
|
grant execute on function public.revoke_device(uuid) to authenticated;
|
|
|
|
-- Replica identity full so UPDATE events deliver the full new row (including
|
|
-- revoked_at) to subscribers; default REPLICA IDENTITY DEFAULT only sends
|
|
-- the primary key columns, which would force a refetch on every event.
|
|
alter table public.devices replica identity full;
|
|
|
|
-- Add devices to the supabase_realtime publication if not already present.
|
|
do $$
|
|
begin
|
|
if not exists (
|
|
select 1
|
|
from pg_publication_tables
|
|
where pubname = 'supabase_realtime'
|
|
and schemaname = 'public'
|
|
and tablename = 'devices'
|
|
) then
|
|
execute 'alter publication supabase_realtime add table public.devices';
|
|
end if;
|
|
end
|
|
$$;
|