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.