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.