Hi,

I'm writing a rather complex application, which stores its main data in 
MySQL and MongoDB.

Now it's time for authorization, which should be ACL driven. And I'm 
looking for your advice whether to use Neo4j (within a Java/Spring 
environment) or not, and if yes, how to design the graph.


*Inspired by Spring Security ACL*, but unhappy about it's limitations with 
the default SQL implementation, I came up with the following thoughts:
ACL_Node:
{
  className: String,
  objectId: String,   (because I have Integer, String and UUID ids)
  parent: ACL_Node,   (relation)
  userId: UUID,       (from MySQL User table)
  roleId: UUID,       (from MySQL Role table)
  permissions: ["READ", "WRITE", ... ]
}


The result would be a huge graph of only ACL_Nodes, with only a single 
Relation "PARENT_OF". Max size of the graph would be COUNT(objects) * 
(COUNT(users) + COUNT(roles)).

There'll be basically only one query (pseudocode):
EITHER
  FIND
    objectId='someObjectId'  AND  userId='currentUserId'
OR
  FIND
    objectId='someObjectId'  AND  roleId IS IN [list of users role ids]
OR
  FIND
    parent of first ACL_Node with objectId='someObjectId' AND REPEAT
(Of course it would look way nicer using Cypher, but at the moment I've 
just executed about 5 different queries with Neo4j ;-) )

I don't know if it scales well, especially the lookup inside the 
permissions array. Any thoguhts?


*Another option* would be to keep the graph smaller, but add way more 
Relations:
User_Node:
{
  userId: UUID    (just a user entity copy from MySQL, but only with its id)
}

Role_Node:
{
  roleId: UUID    (again just a copy from MySQL role table)
}

Object_Node:
{
  className: String,
  objectId: String
}
And then I would just have a look, if the User has a direct Relation (= 
Permission) to the given Object, or if the User is related to a Role that 
has a direct Relation to the object.
I could also create a separate "Class" Node, if that gives any benefit.

But: In this scenario, I can't imagine how to describe the following 
situation (overriding Permissions):
User U is related to Role R
Object O has READ access by Role R
Object O has NO READ access by User U
(I don't know if there's any need for this scenario at all, but it would be 
cool if it works, because User's Permission should match before Role's 
Permission)


*Or is it still better/faster to use SQL*, with some table layout like:
class:               { id, className }
object:              { id, class_id, objectId, parent_object_id }
user_acl:            { id, object_id, user_id }
role_acl:            { id, object_id, role_id }
permission:          { id, permissionName }
user_acl_permission: { id, user_acl_id, permission_id, granted }
role_acl_permission: { id, role_acl_id, permission_id, granted }
This schema would result in a lot of JOINs, so it maybe should be 
denormalized somehow.



*The basic requirements are:*

   - a User can have several Roles
   - a User/Role can have several granted and explicitly *not* *granted* 
   Permissions for an Object
   - each Object can have a parent Object
   - Object Ids must be of different types, so maybe simply use String or 
   (if it's possible) byte[] ?
   - number of Permissions is not fixed, so I *can't *rely on CRUD, because 
   there are several objects which have a more permissions. For example: A 
   User is allowed to edit the description of Object X, but is not allowed to 
   add element's to some List inside Object X.


*Why not simply use Spring Security's default ACL:*

   - It only allows to have 32 distinct roles for each Object, which might 
   be okay for now, but:
      - It's a limitation, that could break my neck someday (and then I 
      have to kill some puppies, you don't want me to do that, right?)
      - It's the same bit mask for every object: Not very descriptive if 
      Bit 6 on Object A means something different than on Object B, but inside 
      the application code it uses the same Name. Or the name will be totally 
      useless like "EXTRA_PERMISSION_1"
   - A graph feels right for this use case, especially with all those 
   parent nodes.
   - And of course, I want to discover this new technology and have a look 
   at my Nodes in that great WebAdmin interface (which is pretty fancy!)

*Why not use Neo4j for all my data:*

   - I don't really know why... I grew up with SQL and I don't know if 
   Neo4j can fit all my needs, like:
      - Storing mainly pure Tree hierarchies (no graph, just tree)
      - Aggregation in general and aggregation of child properties, i.e. 
      Give me the sum of time spent on Project P, by summing up 
      P.getTasks().getTimeSpent()
      - Calculation with Money using GROUP BY, searches with date ranges, 
      etc. pp.
      - Pagination with multiple ORDER BY and multiple WHERE clauses. (I 
      know Neo4j can do, but what about performance with 100000 entries to 
order?)
      - Storing CLOBs (at the moment I'd use MongoDB for that) and Files 
      (MongoDB GridFS)
      - It's a RESTful service, though with MySQL I have to query/join most 
      of the time 2 or 3 tables, to get the result I'd like to have.
   

*Thanks in advance!*

Btw: When looking for RDBMS vs. Neo4j comparisons, there's always just ONE 
example: Social Graph... I know you guys have a lot of experience, though: 
In what scenarios it is way better to use an RDBMS?

-- 
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