Summary I have the following graph structure and the idea is that manager has certain permissions on given resources As seen in the picture, there are three resources and one context (manager). Further we see some inheritance on the resources. break is owned by shift . And lunch is owned by break. I want to design a query that returns all shortest paths from the manager to each resource. For example the shortest path from manager to shift will be the permission relationship seen going out from the manager where the permitted field is allowed. The question lies with finding the shortest path to break. Ideally, I want the shortest path to break to go via shift and not via lunch. In other words permissions present on the parent are to be inherited for a child without any direct permissions
What I have tried: I did manage to write the correct query but here's my problem - the result correctly eliminates a few resources
Code Here is the query I have tried so far. It correctly computes the shortest path to resources with one catch - it considers both the shortest path to break . One via lunch [should not happen] and one via shift [I want this]. Further it omits shift all together because it is purely an "ancestor" (refer to the query) and not a "child" which I understand.
MATCH (ancestors:Resource)<-[:OWNED_BY*..15]-(child:Resource)
MATCH (principal:Resource{id: "p-id"})<-[grant:GRANTED_TO]-(context:Context{id:"c-id"})-[permission:PERMISSION]->(ancestors), path = allShortestPaths((context)-[*..15]-(child))
RETURN DISTINCT path
Here's the output for the query when executed in my browser.
ut here's my problem - the result correctly eliminates a few resources
Code Here is the query I have tried so far. It correctly computes the shortest path to resources with one catch - it considers both the shortest path to break . One via lunch [should not happen] and one via shift [I want this]. Further it omits shift all together because it is purely an "ancestor" (refer to the query) and not a "child" which I understand.
MATCH (ancestors:Resource)<-[:OWNED_BY*..15]-(child:Resource)
MATCH (principal:Resource{id: "p-id"})<-[grant:GRANTED_TO]-(context:Context{id:"c-id"})-[permission:PERMISSION]->(ancestors), path = allShortestPaths((context)-[*..15]-(child))
RETURN DISTINCT path
Here's the output for the query when executed in my browser.
{
"start": {
"identity": 22,
"labels": [
"Context"
],
"properties": {
"name": "manager",
"id": "adef1b8c-3141-44bc-a1ec-1644fa6db79a"
}
},
"end": {
"identity": 41,
"labels": [
"Resource"
],
"properties": {
"name": "break",
"context_id": "",
"id": "b8519676-312a-4ba4-8004-404c7d782706",
"source_id": "break-guid"
}
},
"segments": [
{
"start": {
"identity": 22,
"labels": [
"Context"
],
"properties": {
"name": "manager",
"id": "adef1b8c-3141-44bc-a1ec-1644fa6db79a"
}
},
"relationship": {
"identity": 4,
"start": 22,
"end": 20,
"type": "PERMISSION",
"properties": {
"permitted": "allow",
"name": "read",
"id": "dad8b6a0-b039-4105-87d4-ca151963e1a7"
}
},
"end": {
"identity": 20,
"labels": [
"Resource"
],
"properties": {
"name": "shift",
"context_id": "",
"id": "2ba8d928-d534-4179-9fad-c85f584ce6d5",
"source_id": "guid"
}
}
},
{
"start": {
"identity": 20,
"labels": [
"Resource"
],
"properties": {
"name": "shift",
"context_id": "",
"id": "2ba8d928-d534-4179-9fad-c85f584ce6d5",
"source_id": "guid"
}
},
"relationship": {
"identity": 21,
"start": 41,
"end": 20,
"type": "OWNED_BY",
"properties": {
}
},
"end": {
"identity": 41,
"labels": [
"Resource"
],
"properties": {
"name": "break",
"context_id": "",
"id": "b8519676-312a-4ba4-8004-404c7d782706",
"source_id": "break-guid"
}
}
}
],
"length": 2.0
}
{
"start": {
"identity": 22,
"labels": [
"Context"
],
"properties": {
"name": "manager",
"id": "adef1b8c-3141-44bc-a1ec-1644fa6db79a"
}
},
"end": {
"identity": 41,
"labels": [
"Resource"
],
"properties": {
"name": "break",
"context_id": "",
"id": "b8519676-312a-4ba4-8004-404c7d782706",
"source_id": "break-guid"
}
},
"segments": [
{
"start": {
"identity": 22,
"labels": [
"Context"
],
"properties": {
"name": "manager",
"id": "adef1b8c-3141-44bc-a1ec-1644fa6db79a"
}
},
"relationship": {
"identity": 24,
"start": 22,
"end": 60,
"type": "PERMISSION",
"properties": {
"permitted": "deny",
"name": "read",
"id": "9b52f239-43b5-4b17-a29a-91bfeebca001"
}
},
"end": {
"identity": 60,
"labels": [
"Resource"
],
"properties": {
"name": "lunch",
"context_id": "",
"id": "8c96482d-517f-4421-b1e8-4f4826438cf1",
"source_id": "lunch-guid"
}
}
},
{
"start": {
"identity": 60,
"labels": [
"Resource"
],
"properties": {
"name": "lunch",
"context_id": "",
"id": "8c96482d-517f-4421-b1e8-4f4826438cf1",
"source_id": "lunch-guid"
}
},
"relationship": {
"identity": 23,
"start": 60,
"end": 41,
"type": "OWNED_BY",
"properties": {
}
},
"end": {
"identity": 41,
"labels": [
"Resource"
],
"properties": {
"name": "break",
"context_id": "",
"id": "b8519676-312a-4ba4-8004-404c7d782706",
"source_id": "break-guid"
}
}
}
],
"length": 2.0
}
{
"start": {
"identity": 22,
"labels": [
"Context"
],
"properties": {
"name": "manager",
"id": "adef1b8c-3141-44bc-a1ec-1644fa6db79a"
}
},
"end": {
"identity": 60,
"labels": [
"Resource"
],
"properties": {
"name": "lunch",
"context_id": "",
"id": "8c96482d-517f-4421-b1e8-4f4826438cf1",
"source_id": "lunch-guid"
}
},
"segments": [
{
"start": {
"identity": 22,
"labels": [
"Context"
],
"properties": {
"name": "manager",
"id": "adef1b8c-3141-44bc-a1ec-1644fa6db79a"
}
},
"relationship": {
"identity": 24,
"start": 22,
"end": 60,
"type": "PERMISSION",
"properties": {
"permitted": "deny",
"name": "read",
"id": "9b52f239-43b5-4b17-a29a-91bfeebca001"
}
},
"end": {
"identity": 60,
"labels": [
"Resource"
],
"properties": {
"name": "lunch",
"context_id": "",
"id": "8c96482d-517f-4421-b1e8-4f4826438cf1",
"source_id": "lunch-guid"
}
}
}
],
"length": 1.0
}
Is there any way to write a query that gives me shortest path (permissions) to all resources and in case there isn't a shortest path, take the permissions of the immediate parent. Any help will be appreciated. Thank you


