Fullfør oppgave 4.1: recompute_access ved edge-endring
Når en tilgangsgivende edge (owner, admin, member_of, reader) opprettes, kalles nå recompute_access() i samme PG-transaksjon som edge-insertet. Dette sikrer at node_access-matrisen alltid er oppdatert — ingen vindu med stale tilgang. Implementasjon: - edge_type_to_access_level() mapper edge-typer til access_level enum - insert_edge_with_access() wrapper edge-insert + recompute_access i tx - Vanlige edges (belongs_to, mentions, etc.) skrives som før (fire-and-forget) Verifisert med SQL-tester: direkte tilgang + transitiv tilgang via belongs_to-edges fungerer korrekt. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
03211e59a5
commit
c20fc9149b
2 changed files with 107 additions and 22 deletions
|
|
@ -554,7 +554,21 @@ fn spawn_pg_insert_node(
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Mapper edge_type til access_level for tilgangsgivende edges.
|
||||||
|
/// Returnerer None for edges som ikke gir tilgang.
|
||||||
|
fn edge_type_to_access_level(edge_type: &str) -> Option<&'static str> {
|
||||||
|
match edge_type {
|
||||||
|
"owner" => Some("owner"),
|
||||||
|
"admin" => Some("admin"),
|
||||||
|
"member_of" => Some("member"),
|
||||||
|
"reader" => Some("reader"),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Spawner en tokio-task som skriver edgen til PostgreSQL i bakgrunnen.
|
/// Spawner en tokio-task som skriver edgen til PostgreSQL i bakgrunnen.
|
||||||
|
/// For tilgangsgivende edges (owner, admin, member_of, reader) kalles
|
||||||
|
/// recompute_access i samme transaksjon — ingen vindu med stale tilgang.
|
||||||
fn spawn_pg_insert_edge(
|
fn spawn_pg_insert_edge(
|
||||||
db: PgPool,
|
db: PgPool,
|
||||||
edge_id: Uuid,
|
edge_id: Uuid,
|
||||||
|
|
@ -566,6 +580,30 @@ fn spawn_pg_insert_edge(
|
||||||
created_by: Uuid,
|
created_by: Uuid,
|
||||||
) {
|
) {
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
let access_level = edge_type_to_access_level(&edge_type);
|
||||||
|
|
||||||
|
if let Some(level) = access_level {
|
||||||
|
// Tilgangsgivende edge: wrap i transaksjon med recompute_access
|
||||||
|
let result = insert_edge_with_access(&db, edge_id, source_id, target_id, &edge_type, &metadata, system, created_by, level).await;
|
||||||
|
match result {
|
||||||
|
Ok(_) => {
|
||||||
|
tracing::info!(
|
||||||
|
edge_id = %edge_id,
|
||||||
|
edge_type = %edge_type,
|
||||||
|
access_level = %level,
|
||||||
|
"Edge + node_access persistert til PostgreSQL"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
tracing::error!(
|
||||||
|
edge_id = %edge_id,
|
||||||
|
error = %e,
|
||||||
|
"Kunne ikke persistere edge + node_access til PostgreSQL"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Vanlig edge uten tilgangspåvirkning
|
||||||
let result = sqlx::query(
|
let result = sqlx::query(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO edges (id, source_id, target_id, edge_type, metadata, system, created_by)
|
INSERT INTO edges (id, source_id, target_id, edge_type, metadata, system, created_by)
|
||||||
|
|
@ -590,9 +628,57 @@ fn spawn_pg_insert_edge(
|
||||||
tracing::error!(edge_id = %edge_id, error = %e, "Kunne ikke persistere edge til PostgreSQL");
|
tracing::error!(edge_id = %edge_id, error = %e, "Kunne ikke persistere edge til PostgreSQL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inserter en tilgangsgivende edge og oppdaterer node_access i én transaksjon.
|
||||||
|
/// source_id = subject (bruker/team), target_id = object (noden det gis tilgang til).
|
||||||
|
async fn insert_edge_with_access(
|
||||||
|
db: &PgPool,
|
||||||
|
edge_id: Uuid,
|
||||||
|
source_id: Uuid,
|
||||||
|
target_id: Uuid,
|
||||||
|
edge_type: &str,
|
||||||
|
metadata: &serde_json::Value,
|
||||||
|
system: bool,
|
||||||
|
created_by: Uuid,
|
||||||
|
access_level: &str,
|
||||||
|
) -> Result<(), sqlx::Error> {
|
||||||
|
let mut tx = db.begin().await?;
|
||||||
|
|
||||||
|
sqlx::query(
|
||||||
|
r#"
|
||||||
|
INSERT INTO edges (id, source_id, target_id, edge_type, metadata, system, created_by)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.bind(edge_id)
|
||||||
|
.bind(source_id)
|
||||||
|
.bind(target_id)
|
||||||
|
.bind(edge_type)
|
||||||
|
.bind(metadata)
|
||||||
|
.bind(system)
|
||||||
|
.bind(created_by)
|
||||||
|
.execute(&mut *tx)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// Kall recompute_access: subject=source_id, object=target_id
|
||||||
|
sqlx::query(
|
||||||
|
"SELECT recompute_access($1, $2, $3::access_level, $4)",
|
||||||
|
)
|
||||||
|
.bind(source_id)
|
||||||
|
.bind(target_id)
|
||||||
|
.bind(access_level)
|
||||||
|
.bind(edge_id)
|
||||||
|
.execute(&mut *tx)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
tx.commit().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Spawner en tokio-task som oppdaterer noden i PostgreSQL.
|
/// Spawner en tokio-task som oppdaterer noden i PostgreSQL.
|
||||||
fn spawn_pg_update_node(
|
fn spawn_pg_update_node(
|
||||||
db: PgPool,
|
db: PgPool,
|
||||||
|
|
|
||||||
3
tasks.md
3
tasks.md
|
|
@ -71,8 +71,7 @@ Uavhengige faser kan fortsatt plukkes.
|
||||||
|
|
||||||
## Fase 4: Tilgangskontroll
|
## Fase 4: Tilgangskontroll
|
||||||
|
|
||||||
- [~] 4.1 `recompute_access` i maskinrommet: ved edge-endring, oppdater `node_access`-matrisen. Håndter direkte edges (owner, admin, member, reader).
|
- [x] 4.1 `recompute_access` i maskinrommet: ved edge-endring, oppdater `node_access`-matrisen. Håndter direkte edges (owner, admin, member, reader).
|
||||||
> Påbegynt: 2026-03-17T14:45
|
|
||||||
- [ ] 4.2 Team-transitivitet: member_of-edge til team → arv tilgang fra teamets edges.
|
- [ ] 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.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.
|
- [ ] 4.4 RLS-policies på PG: `node_access`-basert filtrering for tunge spørringer.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue