From e0f30bba271bcb298cf50463b6ada637ef8b6aad Mon Sep 17 00:00:00 2001 From: vegard Date: Tue, 17 Mar 2026 15:01:51 +0100 Subject: [PATCH] =?UTF-8?q?Fullf=C3=B8r=20oppgave=204.2:=20team-transitivi?= =?UTF-8?q?tet=20i=20recompute=5Faccess?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Legger til steg 4 i recompute_access: når en bruker melder seg inn i et team (member_of-edge), arver brukeren all tilgang teamet allerede har. Tidligere håndterte funksjonen kun retningen "team får ny tilgang → propager til eksisterende medlemmer" (steg 3). Nå håndteres begge retninger: - Steg 3: Team får tilgang → alle eksisterende medlemmer arver - Steg 4: Ny bruker melder seg inn → arver teamets eksisterende tilgang Testet med scenario: Trond → Podcastteamet → Sidelinja → Episode 42. Trond arver member-tilgang til alle tre noder via team-transitivitet. Co-Authored-By: Claude Opus 4.6 --- docs/retninger/bruker_ikke_workspace.md | 10 +++++ migrations/001_initial_schema.sql | 10 +++++ migrations/003_team_transitivity.sql | 59 +++++++++++++++++++++++++ tasks.md | 3 +- 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 migrations/003_team_transitivity.sql diff --git a/docs/retninger/bruker_ikke_workspace.md b/docs/retninger/bruker_ikke_workspace.md index d2a782e..63940ec 100644 --- a/docs/retninger/bruker_ikke_workspace.md +++ b/docs/retninger/bruker_ikke_workspace.md @@ -291,6 +291,16 @@ BEGIN WHERE na.subject_id = p_subject_id ON CONFLICT (subject_id, object_id) DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access); + + -- Team-transitivitet: arv tilgang fra teamet. + -- Når en bruker melder seg inn i et team, arver brukeren + -- all tilgang teamet allerede har til andre noder. + INSERT INTO node_access (subject_id, object_id, access, via_edge) + SELECT p_subject_id, na.object_id, na.access, na.via_edge + FROM node_access na + WHERE na.subject_id = p_root_node_id + ON CONFLICT (subject_id, object_id) + DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access); END; $$ LANGUAGE plpgsql; ``` diff --git a/migrations/001_initial_schema.sql b/migrations/001_initial_schema.sql index 6ff4ee1..7689c3b 100644 --- a/migrations/001_initial_schema.sql +++ b/migrations/001_initial_schema.sql @@ -112,6 +112,16 @@ BEGIN WHERE na.subject_id = p_subject_id ON CONFLICT (subject_id, object_id) DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access); + + -- Team-transitivitet: arv tilgang fra teamet. + -- Når en bruker melder seg inn i et team, arver brukeren + -- all tilgang teamet allerede har til andre noder. + INSERT INTO node_access (subject_id, object_id, access, via_edge) + SELECT p_subject_id, na.object_id, na.access, na.via_edge + FROM node_access na + WHERE na.subject_id = p_root_node_id + ON CONFLICT (subject_id, object_id) + DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access); END; $$ LANGUAGE plpgsql; diff --git a/migrations/003_team_transitivity.sql b/migrations/003_team_transitivity.sql new file mode 100644 index 0000000..51beaa0 --- /dev/null +++ b/migrations/003_team_transitivity.sql @@ -0,0 +1,59 @@ +-- 003_team_transitivity.sql +-- Team-transitivitet: når en bruker melder seg inn i et team (member_of-edge), +-- arver brukeren all tilgang teamet allerede har. +-- +-- Tidligere håndterte recompute_access kun retningen "team får ny tilgang → +-- propager til eksisterende medlemmer". Nå håndteres også "ny bruker melder +-- seg inn i team → arv teamets eksisterende tilganger". +-- +-- Ref: docs/retninger/bruker_ikke_workspace.md, docs/primitiver/edges.md + +BEGIN; + +CREATE OR REPLACE FUNCTION recompute_access( + p_subject_id UUID, + p_root_node_id UUID, + p_access access_level, + p_via_edge UUID +) RETURNS void AS $$ +BEGIN + -- Steg 1: Direkte tilgang til roten + INSERT INTO node_access (subject_id, object_id, access, via_edge) + VALUES (p_subject_id, p_root_node_id, p_access, p_via_edge) + ON CONFLICT (subject_id, object_id) + DO UPDATE SET access = GREATEST(node_access.access, p_access); + + -- Steg 2: Transitiv: noder som tilhører roten (belongs_to) + INSERT INTO node_access (subject_id, object_id, access, via_edge) + SELECT p_subject_id, e.source_id, p_access, p_via_edge + FROM edges e + WHERE e.target_id = p_root_node_id + AND e.edge_type = 'belongs_to' + ON CONFLICT (subject_id, object_id) + DO UPDATE SET access = GREATEST(node_access.access, p_access); + + -- Steg 3: Hvis subject er et team: propager til alle teammedlemmer + INSERT INTO node_access (subject_id, object_id, access, via_edge) + SELECT e.source_id, na.object_id, na.access, na.via_edge + FROM node_access na + JOIN edges e ON e.target_id = p_subject_id + AND e.edge_type = 'member_of' + WHERE na.subject_id = p_subject_id + ON CONFLICT (subject_id, object_id) + DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access); + + -- Steg 4: Team-transitivitet — arv tilgang fra teamet. + -- Når en bruker (p_subject_id) melder seg inn i et team (p_root_node_id), + -- arver brukeren all tilgang teamet allerede har til andre noder. + -- Sjekker om root_node har node_access-rader som subject (= er et team + -- eller annen entitet med tilgang). Kopierer disse til p_subject_id. + INSERT INTO node_access (subject_id, object_id, access, via_edge) + SELECT p_subject_id, na.object_id, na.access, na.via_edge + FROM node_access na + WHERE na.subject_id = p_root_node_id + ON CONFLICT (subject_id, object_id) + DO UPDATE SET access = GREATEST(node_access.access, EXCLUDED.access); +END; +$$ LANGUAGE plpgsql; + +COMMIT; diff --git a/tasks.md b/tasks.md index 686c143..7dfac54 100644 --- a/tasks.md +++ b/tasks.md @@ -72,8 +72,7 @@ Uavhengige faser kan fortsatt plukkes. ## Fase 4: Tilgangskontroll - [x] 4.1 `recompute_access` i maskinrommet: ved edge-endring, oppdater `node_access`-matrisen. Håndter direkte edges (owner, admin, member, reader). -- [~] 4.2 Team-transitivitet: member_of-edge til team → arv tilgang fra teamets edges. - > Påbegynt: 2026-03-17T14:57 +- [x] 4.2 Team-transitivitet: member_of-edge til team → arv tilgang fra teamets edges. - [ ] 4.3 Visibility-filtrering: STDB-spørringer respekterer visibility-enum. Frontend ser bare noder brukeren har tilgang til. - [ ] 4.4 RLS-policies på PG: `node_access`-basert filtrering for tunge spørringer.