let me try to explain how exactly ACLs in Baqend work.
TL;DR
To secure your object /db/Companies/123-456-789
you can simply add an allow rule for each of your three user ids (/db/Users/10
. /db/Users/11
, /db/Users/12
) to the object acls of your company object like this:
db.Companies.load("/db/Companies/123-456-789").then(function(company) {
company.allowWriteAccess("/db/Users/10");
company.allowWriteAccess("/db/Users/11");
company.allowWriteAccess("/db/Users/12");
return company.save();
})
This ensures that only these users can edit the company object. Notably, this list of rules is independent of the list of admins contained in your company object. To revoke the write access of a user, you can use deleteWriteAccess
in the same way we used allowWriteAccess
before.
This means your users can leave a Company easily without leaving your app.
I hope this answers your question. Because ACLs are complex I will try to explain the general approach in more detail now.
How ACLs Work
On which level can access be controlled?
There are two levels to control access to your data:
- On table level (so-called Schema ACLs)
- On object level (so-called Object ACLs)
Schema ACLs define who is allowed access to the table in general. For example, you could define that the User table is not readable for the public by granting read access only to the admin:
allowReadAccess("/db/Role/admin") // Schema ACLs can only be set by the admin
You can define rules for reading, updating, inserting and querying on the table separately.
Object ACLs defines access on the lower level. You can use it to deny access to a specific object. For example, you could define that only the user itself can update its own User object, like this:
allowWriteAccess("<userId>")
For objects, you can define rules for reading and writing separately.
Who has access now (how are permission evaluated)?
In order to access an object, a user needs to have general permission to access the table (Schema ACLs) and also permission to access the object itself (Object ACLs). This means the Schema ACLs are evaluated first if they grant you access, the Object ACLs are evaluated as well.
Which rules can I define?
There are two types of rules that can be defined to allow or deny access:
- Allow Rules define who has access in general. These rules are checked first. If you do not define allow rules, everyone has general access.
- Deny Rules defines who is denied access (even if the user was allowed by an allow rule). These rules are checked after the allow rules.
Take a look at the JS API for ACLs for the actual method documentation.
These separate rules can be tricky at the start but they are really powerful. Let's do some examples. How can I use these rules to ...
- Deny access for everyone: --> Set the only allow rule for admin
- Allow access for logged-in users but not for some guy Peter (like when you block someone is a chat application): --> Set an allow rule for the
loggedin
role and a deny rule for Peter.
- Only allow access from backend code modules: --> Set an allow rule for the
node
role (see below for the explanation of Roles).
Who can I grant or deny access?
There are two entities you can use in your allow and deny rules:
- Users from the predefined User table can be granted or denied access
- Groups of Users defined in the predefined Role table can be granted or denied access
- The predefined roles
admin
, loggedin
(represents all logged-in users) and node
(represents backend code modules that access the database)
What is the default access for my tables?
Tables and objects are publically accessible by default if not configured otherwise.
What about attribute-level ACLs
There are no attribute level ACLs in Baqend. This means when you have a User object with a private email address and a public name you can only make the object private or public.
The solution for this is to use two objects, one for the private information and one for the public information and then link the two. For the User, this would mean you make the actual User object private and define a new Profile table where you keep the public user information.
While this solution is more work when defining your schema, there are good reasons why Baqend does not support attribute-level ACLs. Without going into too much detail:
- Better caching. Attribute-level ACLs would severely limit how we can cache and therefore accelerate your database requests.
- Expensive evaluation. Attribute-level ACLs are much harder to evaluate and therefore slow down database access. Object-level ACLs, on the other hand, can be pushed down to our database system and are evaluated very efficiently.
Something missing
I hope these explanations help to understand the ACL system better. If there is something missing here, just comment and I will add it.