Use cases

Embedded graphs in tests and applications

The engine is a Rust library. A graph opens in memory in microseconds, so a unit test can build one, query it and throw it away, and an application can keep one next to its own data without running a database server.

The problem

Permission checks are a graph question: a user belongs to groups, groups nest, folders contain documents, and "may Ann read this file?" is a path through all of it. In SQL that is a recursive query per check; with a server database it is a container in every test run.

Embedded, the same check is one Cypher pattern against a graph that lives in your process. Tests use the in-memory mode; the application opens the same graph durably with one changed line.

Try it with this dataset

Three users, four nested groups, three folders and four documents. Run this in your GraphBuff checkout (get one in a single command); it downloads access.cypher, loads it and leaves you in the shell.

$ curl -O https://graphbuff.com/datasets/access.cypher
$ cargo run --release -p graphbuff-cli -- -i access.cypher
14 nodes created, 16 relationships created, 14 properties set, 14 labels added

What may Ann read?

Query 1

Follow group membership to any depth, then the read grant, then folder contents to any depth.

MATCH (u:User {name: 'ann'})-[:MEMBER_OF*]->(:Group)-[:CAN_READ]->(top)-[:CONTAINS*0..]->(item:Doc)
RETURN DISTINCT item.name AS readable ORDER BY readable;
+----------------------+
| readable             |
+----------------------+
| "/deploy/keys.txt"   |
| "/deploy/runbook.md" |
| "/handbook.md"       |
| "/src/main.rs"       |
+----------------------+
4 rows

Who may read the deploy keys?

Query 2

The same pattern walked from the document back to the users.

MATCH (d:Doc {name: '/deploy/keys.txt'})<-[:CONTAINS*0..]-(top)<-[:CAN_READ]-(:Group)<-[:MEMBER_OF*]-(u:User)
RETURN DISTINCT u.name AS user ORDER BY user;
+-------+
| user  |
+-------+
| "ann" |
| "bob" |
+-------+
2 rows

Why is Ann allowed?

Query 3

The shortest path is the explanation an audit log needs.

MATCH p = shortestPath((u:User {name: 'ann'})-[:MEMBER_OF|CAN_READ|CONTAINS*]->(d:Doc {name: '/deploy/keys.txt'}))
RETURN [n IN nodes(p) | n.name] AS because;
+----------------------------------------------------------+
| because                                                  |
+----------------------------------------------------------+
| ["ann", "on-call", "ops", "/deploy", "/deploy/keys.txt"] |
+----------------------------------------------------------+
1 row

The same check in a Rust test

Rust

Add the dependency from the Download page, load the dataset with include_str! and assert on the result. Cargo dependency.

use graphbuff::{params, Database};

#[test]
fn ann_may_read_the_deploy_keys() -> Result<(), Box<dyn std::error::Error>> {
    let db = Database::in_memory();
    for statement in include_str!("access.cypher").split(';') {
        if !statement.trim().is_empty() {
            db.execute(statement)?;
        }
    }

    let result = db.execute_with_params(
        "MATCH (u:User {name: $user})-[:MEMBER_OF*]->(:Group)-[:CAN_READ]->(top)
               -[:CONTAINS*0..]->(d:Doc {name: $doc})
         RETURN count(*) AS grants",
        &params! { "user" => "ann", "doc" => "/deploy/keys.txt" },
    )?;
    assert!(result.get(0, "grants").and_then(|v| v.as_int()).unwrap_or(0) > 0);
    Ok(())
}

Not running GraphBuff yet?

$ docker run --rm -p 127.0.0.1:7475:7475 -p 127.0.0.1:7687:7687 ghcr.io/janvencl/graphbuff --demo movies

Needs Docker. Full walkthrough