Hi Benjamin,

how about setting up your example as  a graph gist (gist.neo4j.org) with a tiny 
sample dataset?

Am 14.07.2014 um 15:28 schrieb Benjamin Makus <[email protected]>:

> I now decided to use Neo4j as my main DB, this will simplify ACL stuff very 
> much.
> 
> So here's my basic schema:
> node User {
>   String username
> }
> 
> node Role {
>   String name
> }
> 
> relationship MEMBER_OF { }
> 
> relationship PARENT_OF { }
> 
> relationship HAS_PERMISSION {
>   boolean read
>   boolean update
>   boolean delete
>   boolean ...
> }
> 
> Each User can be MEMBER_OF many roles.
> Each User can have a HAS_PERMISSION relation to every other node (i.e. 
> Article, Event, ...).
> Each Role can have a HAS_PERMISSION relation to every other node (i.e. 
> Article, Event, ...).
> Each HAS_PERMISSION relation defines what is allowed and what's not allowed. 
> This can be different actions dependent on the node, i.e. Article has an 
> "addComment" and a "publish" Permission, whereas Event doesn't have those 
> Permissions.
> Each secured node can have a PARENT_OF relation to another node, but for 
> example Article will never have a parent, because it's always at root level 
> of my application.
> 
> This approach looks very flexible, but I'm stuck with the queries... I had a 
> look at your ACL example, here: 
> http://docs.neo4j.org/chunked/stable/examples-acl-structures-in-graphs.html
> 
> Reference Node?
> Is there any reason to use a Reference Node instead of Labels?
Use Labels
> Query #1:
> Input: User node u, some secured Node s
> Query: Find the first HAS_PERMISSION relation, that connects u and s
> Returns: the HAS_PERMISSION relation
> I thought about using shortestPath(), but that doesn't fit in all situations.
MATCH path = shortestPath((u:User 
{username:{name}})-[:HAS_PERMISSION*]->(s:Article {id:{articleId}))
RETURN path
> Query #2:
> Input: User node u, some Label l, a Permission p
> Query: Find all nodes, labeled with Label l, where User u is somehow related 
> to via HAS_PERMISSION and HAS_PERMISSION has Permission p set to true
> Returns: List of nodes, labeled with Label l

MATCH (u:User {username:{name}})-[:HAS_PERMISSION {read:true}*]->(node:Label)
RETURN n

I'd probably change the HAS_PERMISSION.permission to
CAN_READ
CAN_WRITE
CAN_PUBLISH
CAN_DELETE

for performance and clarity reasons.


> Basically both queries can use a similar algorithm, but I need some kind of 
> precedence in it, so it will find the right HAS_PERMISSION relation. It's 
> like:

What does "first" mean ?
> User takes precedence over Role
> Secured Node takes precedence over its parent
> This means: If I have a graph, where
> User u has Write Access to the Parent p of Secured Node s
> Some Role r of the User u has only Read Access to Secured Node s
> Then the User u will have write access to Secured Node s, because it has to 
> match the Users permissions first.

Don't you ask for a certain permission in the first place?

You could filter paths after the fact or order them by the number of roles and 
parents (and minimize that number) ?

return path, 
length(FILTER (n in nodes(path) WHERE n:Role)) as roles,
length(FILTER (n in nodes(path) WHERE (n)<-[:PARENT_OF]-() )) as parents
order by roles + parents asc

> 
> And there's another scenario:
> User's Role r1 has Write Access = false for Secured Node s
> User's Role r2 has Write Access = true for Secured Node s
> Then of the write access must be granted.

this would be easier with the CAN_WRITE relationship which then wouldn't exist 
in your case 1

Otherwise you have to filter them out, that's why you'd only look for paths 
with -[:HAS_PERMISSION {write:true}]->
> 
> 
> Sorry for this huge post, but I can't figure out how to do that...

No worries, happy to help. Please write it up as a graphgist, this will 
definitely be helpful to others too. (If you need help with that ping me).

Michael
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "Neo4j" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"Neo4j" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to