如何使用 gremlin 查询权限图?

How do I query a permissions graph using gremlin?

我有下图:

我正在使用 Tinkergraph 来尝试找出:

  1. 用户#1是否对资源#1具有"read"权限? (它没有)
  2. User#2 是否对 Resource#1 具有 "write" 权限? (确实如此)。

我还试图找到一个不特定于这个确切图形的查询,因为在现实生活模型中,它们之间可能存在多个层次角色。我刚刚开始掌握 Gremlin 语法,但我发现这个特定的查询难以捉摸。这是创建上图的代码:

    Graph graph = TinkerGraph.open();
    Vertex user1 = graph.addVertex(T.label, "user", T.id, 1, "name", "marko");
    Vertex user2 = graph.addVertex(T.label, "user", T.id, 2, "name", "vadas");
    Vertex role1 = graph.addVertex(T.label, "role", T.id, 3, "name", "role_1");
    Vertex role2 = graph.addVertex(T.label, "role", T.id, 4, "name", "role_2");
    Vertex resource1 = graph.addVertex(T.label, "resource", T.id, 5, "name", "resource_1");
    Vertex resource2 = graph.addVertex(T.label, "resource", T.id, 6, "name", "resource_2");

    user1.addEdge("read", resource2, T.id, 7);
    user1.addEdge("member", role2, T.id, 8);
    user2.addEdge("owns", resource2, T.id, 9);
    user2.addEdge("member", role1, T.id, 10);

    role1.addEdge("child_of", role2, T.id, 11);
    role1.addEdge("read", resource1, T.id, 12);

    role2.addEdge("write", resource1, T.id, 13);
    role2.addEdge("write", resource2, T.id, 14);

我目前尝试回答问题 #1 是使用 repeat,从 User#1 开始,然后沿着路径找到 "outEdge"标签 "read" 通向顶点 Resource#1.

啊哈,在我写这篇文章的时候,我可能刚刚弄明白了,但由于我是 Gremlin 的新手,也许熟悉 Gremlin 的人可以对其进行理智检查,或者告诉我是否有更好的方法?如果没有,那么也许这会对试图解决同样问题的其他人有所帮助。

q1 = graph.traversal().V(user1.id())
    .repeat(__.out().simplePath())
    .until(__.outE().hasLabel("read").inV().is(resource1)).path().toList();
// q1 returns [] (which is expected)

q2 = graph.traversal().V(user2.id())
    .repeat(__.out().simplePath())
    .until(__.outE().hasLabel("write").inV().is(resource1)).path().toList();
// q2 returns [[v[2], v[3], v[4]]]  (which seems right too)

你不应该遍历任意边(没有标签限制)。我想你正在寻找

  1. 直接连接到资源
  2. 从用户角色到资源的连接或
  3. 从任何父角色到资源的连接

在单个查询中涵盖所有三种情况的最佳方法是从用户开始,遍历所有 memberchild_of 边,发出沿路径的所有顶点并最终检查是否从任何顶点到资源都有 read / write 连接:

gremlin> // Does User#1 have "read" permission on Resource#1? (it does not)
gremlin> g.V(1).emit().
             repeat(out("member","child_of")).
           out("read").has("name","resource_1").hasNext()
==>false

gremlin> // Does User#2 have "write" permission on Resource#1? (it does).
gremlin> g.V(2).emit().
             repeat(out("member","child_of")).
           out("write").has("name","resource_1").hasNext()
==>true