So I think the key thing to start with is the observation that roles have privileges, and users do not. I'm not saying it works this way under the covers, but the way to think of it is like this:
(:User)-[:HAS]->(:Role)-[:HAS]->(:Privilege)-[:SCOPED_TO]->(:Graph)
Privileges are inherently bound to specific databases, or graphs. If you do SHOW PRIVILEGES
on system
, then you'll see the results come back with a "graph" field. If you do GRANT CREATE INDEX ON DATABASE db1 TO indexAdmin
then "graph" will be "db1". (In Neo4j 4.0, graphs and databases are basically the same thing, but it's called "graph" and not "database" to leave open the possibility that in the future, a single database could contain multiple namespaced / addressable graphs)
So those I think are important fundamentals. So when you ask whether you can grant a user a role only on a particular database, the answer is no -- because "which database are we talking about" is baked into the privilege definition itself. And users can't have privileges, only roles can.
Note that the special reserved roles of admin, reader, architect -- in SHOW PRIVILEGES report that their graph is '*'
, which gives you part of the answer. You can't grant admin only on one database, and if you do grant admin to a user, because admin has certain privileges on graph *
, they get admin everywhere. So you effectively can't express ideas like 'user foo has role admin, except on database supersecret'
So I think the solution in your case should be to define database-specific roles. For example:
CREATE ROLE db1Admin
GRANT ALL DATABASE PRIVILEGES ON DATABASE db1 TO db1Admin
And then grant db1Admin to whatever user needs it. Same approach for all other privilege sets that you'd want to grant. In effect, roles are bound to databases, users are not.
Related caveats that derive from how this works: GRANT/REVOKE/DENY on a role affects all users with that role