Reputation: 115
Is there any way of using ACL in Parse Server to deny access to items for a specific user or role?
Say I have a social networking app where users post updates. I have a role called all_users
which all registered users are added to. All updates are readable by this role, EXCEPT users that the author has blocked.
I can grant read and write access to users/roles, but removing both read and write access through the Parse Dashboard removes the entry completely.
Tips would be greatly appreciated.
Upvotes: 2
Views: 607
Reputation: 1602
I wasn't 100% sure the answer, so I did what I usually do, make a unit test to figure it out.
As it happens, I am working on a PR to create an 'all user role' that will improve on your current solution for that, especially if your social network takes off and you have many many users.
See the issue: https://github.com/parse-community/parse-server/issues/4107
You can track the current state of my solution (which currently works, but isn't ready to merge just yet) here: https://github.com/parse-community/parse-server/pull/4111
But all I'm working on is the 'all user role' case, not the 'deny a user' case you need.
What I did to test your question was extend the unit test from my pr to address your particular (interesting) use case:
it('should respect for read.', function (done) {
let role, user;
const userP = new Parse.User()
.set('username', 'userA')
.set('password', 'password')
.save()
.then((user) => Parse.User.logIn(user.get('username'), 'password'));
const roleP = new Parse.Role('aRole', new Parse.ACL())
.save();
Parse.Promise.when(userP, roleP)
.then((newUser, newrole) => {
user = newUser;
role = newrole;
const acl = new Parse.ACL();
acl.setRoleReadAccess(role, true);
return new Parse.Object('Foo')
.setACL(acl)
.save();
})
.then(() => new Parse.Query('Foo').first())
.then((obj) => {
expect(obj).not.toBeDefined();
return new Parse.Query(Parse.Role)
.equalTo('name', '_All_Role')
.first()
})
.then((allRole) => {
expect(allRole).toBeDefined();
const roles = role.relation('roles');
roles.add(allRole);
return role.save(null, { useMasterKey: true });
})
.then(() => new Parse.Query('Foo').first())
.then((obj) => {
expect(obj).toBeDefined();
const acl = obj.getACL();
acl.setReadAccess(user.id, false); // <--- this is what you want!!!
console.log(acl);
const valid = obj.setACL(acl);
expect(valid).toBe(true);
return obj.save();
})
.then(() => new Parse.Query('Foo').first())
.then((obj) => {
expect(obj).not.toBeDefined(); // <--- but this fails :(....
done();
})
.catch(done.fail);
});
As I suspected, the test failed. I'm not an expert on parse permission (though learning) but my current understanding is that in there is no concept of precedence, so once you have added the permission through your everyone group, there is no way to 'deny'. In other words, the current permission model is that permissions are added, not explicitly denied.
Your use case is compelling though so finding a way to accommodate your use case would be interesting. As is often the case though, either you're going to need to figure out how to add it in such a way that it would be acceptable for the general use cases too or recruit someone who can (not volunteering, my dance card is full :).
Upvotes: 1