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