Files
teamvis-selfhost/supabase/migrations/0061_portal_api_tokens.sql
T

41 lines
2.1 KiB
SQL

-- ====================================================================
-- 0061_portal_api_tokens — Bearer-Token für die native App (iOS/Android)
-- ====================================================================
-- Die native App (React Native/Expo) kann keine Server Actions und kein
-- iron-session-Cookie nutzen. Sie authentifiziert über den bestehenden
-- Magic-Link-Code-Flow und erhält danach einen langlebigen Bearer-Token,
-- der im Gerät (Expo SecureStore / Keychain) liegt und bei jedem
-- /api/portal/*-Request im Authorization-Header mitgeschickt wird.
--
-- Identität = E-Mail (wie die Portal-Session, lib/portal-session.ts). Eine
-- Person kann mehrere aktive Karten/Profile mit derselben E-Mail haben;
-- active_employee_id hält das zuletzt gewählte Profil (bei Multi-Profil),
-- ist bei genau einem Profil bedeutungslos.
--
-- Sicherheit: Es wird NUR der SHA-256-Hash des Tokens gespeichert (wie bei
-- Admin-Invites) — ein DB-Leak gibt keine gültigen Tokens preis. Zugriff
-- ausschließlich über Service-Role (die Route-Handler), kein anon-Zugriff.
-- Gleitende Gültigkeit: expires_at rückt bei aktiver Nutzung nach vorne
-- (analog zur 90-Tage-Trusted-Portal-Session).
create table if not exists public.portal_api_tokens (
id uuid primary key default gen_random_uuid(),
email text not null,
token_hash text not null unique,
-- Zuletzt gewähltes Profil bei Multi-Profil. NULL = noch nicht gewählt
-- bzw. Single-Profil (dann löst der Server das eine aktive Profil auf).
active_employee_id uuid references public.employees(id) on delete set null,
user_agent text,
created_at timestamptz not null default now(),
last_used_at timestamptz not null default now(),
expires_at timestamptz not null,
revoked_at timestamptz
);
create index if not exists portal_api_tokens_email_idx
on public.portal_api_tokens (email);
-- RLS an, keine anon-Policy → Default-Deny für anon. Service-Role umgeht RLS.
alter table public.portal_api_tokens enable row level security;
revoke all on public.portal_api_tokens from anon;