107 lines
4.8 KiB
SQL
107 lines
4.8 KiB
SQL
-- =====================================================================
|
|
-- TeeCup — Reaksjoner (emoji) + trådede kommentarer på innlegg,
|
|
-- migrasjon 059 (ADR-046).
|
|
--
|
|
-- To tabellpar, ett per eksisterende "innlegg"-tabell -- IKKE én
|
|
-- polymorf tabell på tvers av tenant-grensen (ADR-044 Beslutning C sin
|
|
-- begrunnelse gjelder identisk her: round_message har ingen
|
|
-- organization_id/RLS (ADR-033 Beslutning A), message har begge
|
|
-- (ADR-025) -- CLAUDE.md sin invariant "organization_id på alle
|
|
-- domenetabeller, håndhevet av RLS" krever egen RLS-håndtering for
|
|
-- org-siden uansett).
|
|
--
|
|
-- Én reaksjon per bruker per innlegg (UPSERT ved bytte av emoji, ikke
|
|
-- en stabel). Kommentarer lagres FLATT med parent_comment_id --
|
|
-- frontend bygger tre-strukturen. Sletting av en kommentar kaskade-
|
|
-- sletter undertråden (samme "kun slett, aldri rediger"-filosofi som
|
|
-- round_message/message selv).
|
|
-- =====================================================================
|
|
\set ON_ERROR_STOP on
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- round_message -- ingen RLS, speiler round_message selv (ADR-033)
|
|
-- ---------------------------------------------------------------------
|
|
|
|
CREATE TABLE round_message_reaction (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
round_message_id uuid NOT NULL REFERENCES round_message(id) ON DELETE CASCADE,
|
|
user_id uuid NOT NULL REFERENCES app_user(id),
|
|
emoji text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
|
|
UNIQUE (round_message_id, user_id)
|
|
);
|
|
|
|
CREATE INDEX round_message_reaction_message_idx ON round_message_reaction (round_message_id);
|
|
|
|
-- INGEN RLS -- samme plain_connection()-mønster som round_message selv.
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON round_message_reaction TO teecup_app;
|
|
|
|
CREATE TABLE round_message_comment (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
round_message_id uuid NOT NULL REFERENCES round_message(id) ON DELETE CASCADE,
|
|
parent_comment_id uuid REFERENCES round_message_comment(id) ON DELETE CASCADE,
|
|
author_user_id uuid NOT NULL REFERENCES app_user(id),
|
|
-- Frosset ved skrivetidspunkt, samme prinsipp som round_message.author_display_name.
|
|
author_display_name text NOT NULL,
|
|
body text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
|
|
CHECK (length(btrim(body)) > 0)
|
|
);
|
|
|
|
CREATE INDEX round_message_comment_message_idx ON round_message_comment (round_message_id, created_at);
|
|
CREATE INDEX round_message_comment_parent_idx ON round_message_comment (parent_comment_id);
|
|
|
|
GRANT SELECT, INSERT, DELETE ON round_message_comment TO teecup_app;
|
|
|
|
-- ---------------------------------------------------------------------
|
|
-- message (lag-chat + org-oppslagstavle) -- RLS'et, org-tenant-invariant
|
|
-- ---------------------------------------------------------------------
|
|
|
|
CREATE TABLE message_reaction (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organization_id uuid NOT NULL REFERENCES organization(id) ON DELETE CASCADE,
|
|
message_id uuid NOT NULL REFERENCES message(id) ON DELETE CASCADE,
|
|
user_id uuid NOT NULL REFERENCES app_user(id),
|
|
emoji text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
|
|
UNIQUE (message_id, user_id)
|
|
);
|
|
|
|
CREATE INDEX message_reaction_message_idx ON message_reaction (message_id);
|
|
|
|
ALTER TABLE message_reaction ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE message_reaction FORCE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY org_isolation ON message_reaction
|
|
USING (organization_id = app_current_org())
|
|
WITH CHECK (organization_id = app_current_org());
|
|
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON message_reaction TO teecup_app;
|
|
|
|
CREATE TABLE message_comment (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
organization_id uuid NOT NULL REFERENCES organization(id) ON DELETE CASCADE,
|
|
message_id uuid NOT NULL REFERENCES message(id) ON DELETE CASCADE,
|
|
parent_comment_id uuid REFERENCES message_comment(id) ON DELETE CASCADE,
|
|
author_user_id uuid NOT NULL REFERENCES app_user(id),
|
|
author_display_name text NOT NULL,
|
|
body text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
|
|
CHECK (length(btrim(body)) > 0)
|
|
);
|
|
|
|
CREATE INDEX message_comment_message_idx ON message_comment (message_id, created_at);
|
|
CREATE INDEX message_comment_parent_idx ON message_comment (parent_comment_id);
|
|
|
|
ALTER TABLE message_comment ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE message_comment FORCE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY org_isolation ON message_comment
|
|
USING (organization_id = app_current_org())
|
|
WITH CHECK (organization_id = app_current_org());
|
|
|
|
GRANT SELECT, INSERT, DELETE ON message_comment TO teecup_app;
|