teecup/011_join_code_and_leading_side.sql

75 lines
3.1 KiB
PL/PgSQL

-- Migrasjon 011: invitasjonskode (oppdagelse) + cachet matchledelse (ADR-020).
--
-- To uavhengige, additive endringer:
-- 1. tournament.join_code -- kort, menneske-skrivbar kode som løses til
-- riktig turnering FØR org-kontekst er kjent (samme "løs kontekst FØR
-- RLS kan håndheve noe"-problem som public_tournament_org, 007).
-- Bevisst OVERSTYRER visibility ved bruk (se ADR-020 Beslutning A) --
-- dette er ikke noe skjemaet håndhever, kun API-laget.
-- 2. match.leading_side -- cachet fortegn av MatchState.lead (ADR-020
-- Beslutning C), samme mønster som status_text/points_side_a/b.
-- ---------------------------------------------------------------------
-- 1. tournament.join_code
-- ---------------------------------------------------------------------
ALTER TABLE tournament ADD COLUMN join_code text;
-- Backfyll eksisterende rader (typisk 1-2 i prod på dette tidspunktet) med
-- en tilfeldig 6-tegns kode fra et alfabet uten forvekslingsbare tegn
-- (0/O, 1/I droppet). Kollisjonssjekk mot allerede-tildelte koder i samme
-- løkke -- radantallet er lite nok til at en enkel retry-løkke er trygg.
DO $$
DECLARE
r RECORD;
alphabet text := 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
candidate text;
attempt int;
i int;
BEGIN
FOR r IN SELECT id FROM tournament WHERE join_code IS NULL LOOP
attempt := 0;
LOOP
candidate := '';
FOR i IN 1..6 LOOP
candidate := candidate || substr(alphabet, 1 + floor(random() * length(alphabet))::int, 1);
END LOOP;
attempt := attempt + 1;
EXIT WHEN attempt > 20 OR NOT EXISTS (
SELECT 1 FROM tournament WHERE join_code = candidate
);
END LOOP;
UPDATE tournament SET join_code = candidate WHERE id = r.id;
END LOOP;
END $$;
ALTER TABLE tournament ALTER COLUMN join_code SET NOT NULL;
ALTER TABLE tournament ADD CONSTRAINT tournament_join_code_unique UNIQUE (join_code);
-- ---------------------------------------------------------------------
-- 2. match.leading_side
-- ---------------------------------------------------------------------
ALTER TABLE match ADD COLUMN leading_side text CHECK (leading_side IN ('a', 'b'));
-- ---------------------------------------------------------------------
-- 3. public_tournament_by_code() -- fjerde SECURITY DEFINER-bro i
-- prosjektet (etter public_tournament_org 007, link_player_by_email 008,
-- public_org_by_slug 009), samme herding (SET search_path = public mot
-- kapring). Eksponerer KUN uuid<-text-koblingen, ingenting annet fra
-- tournament-raden. NULL for ukjent kode -- ingen egen anti-
-- enumereringsbekymring her siden koden er MENT å deles (se ADR-020
-- Beslutning A), men samme returform som de tre andre broene uansett.
-- ---------------------------------------------------------------------
CREATE FUNCTION public_tournament_by_code(p_code text)
RETURNS uuid
LANGUAGE sql
SECURITY DEFINER
SET search_path = public
STABLE
AS $$
SELECT id FROM tournament WHERE upper(join_code) = upper(p_code);
$$;
GRANT EXECUTE ON FUNCTION public_tournament_by_code(text) TO teecup_app;