How do you map predicates to objects and/or users?
realnot opened this issue · comments
I'm trying to build this permission mapping
Users | Permissions | Object |
---|---|---|
Bob | Can edit book | Lord of the rings |
Bob | Can edit book | Harry Potter |
Bob | Can read book | Lord of the rings |
Bob | Can read book | Harry Potter |
Tim | Can edit book | Lord of the rings |
Tim | Can edit book | Harry Potter |
Tim | Can read book | Lord of the rings |
Tim | Can read book | Harry Potter |
But from the documentation I don't see how "Bob and Tim can edit Lord of the rings". Bob is not in any group and is not the owner of the book. Basically what is missing is a table to map Users, Permissions, Objects.
Predicates can be created from any callable that accepts anything from zero to two positional arguments
All examples show a predicate with user and object as arguments, but not a "permission". How do you test against above matrix? One way would be create a table like:
Users | Permissions | Content Type | Object ID |
---|---|---|---|
1 (Bob) | 1 (Can edit book) | 1 (books) | 1 (Lord of the Rings) |
1 (Bob) | 1 (Can edit book) | 1 (books) | 2 (Harry Potter) |
1 (Bob) | 2 (Can read book) | 1 (books) | 1 (Lord of the Rings) |
1 (Bob) | 2 (Can read book) | 1 (books) | 2 (Harry Potter) |
1 (Bob) | 3 (Can drive cars) | 2 (cars) | 1 (Ferrari SF90) |
1 (Bob) | 3 (Can drive cars) | 2 (cars) | 2 (Fiat 500) |
1 (Bob) | 4 (Can fix cars) | 2 (cars) | 1 (Ferrari) |
1 (Bob) | 4 (Can fix cars) | 2 (cars) | 2 (Fiat 500) |
2 (Tim) | 1 (Can edit book) | 1 (books) | 1 (Lord of the Rings) |
2 (Tim) | 1 (Can edit book) | 1 (books) | 2 (Harry Potter) |
2 (Tim) | 2 (Can read book) | 1 (books) | 1 (Lord of the Rings) |
2 (Tim) | 2 (Can read book) | 1 (books) | 2 (Harry Potter) |
2 (Tim) | 3 (Can drive cars) | 2 (cars) | 1 (Ferrari SF90) |
2 (Tim) | 3 (Can drive cars) | 2 (cars) | 2 (Fiat 500) |
2 (Tim) | 4 (Can fix cars) | 2 (cars) | 1 (Ferrari) |
2 (Tim) | 4 (Can fix cars) | 2 (cars) | 2 (Fiat 500) |
And from the view you have:
- required permissions
- user from request
- current object_id (from get_object) which take you to step 4
- get content_type with object_id
Now you have to test that all permissions you retrieve from the table are in required permission defined by view. Is the right approach or there's another way?
I would probably change it so you have all 4 CRUD methods on the same row with a BooleanField
for each:
class BookPermission(RulesModel):
user = models.ForeignKey(User, on_delete=models.CASCADE)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
can_add = models.BooleanField(default=False)
can_view = models.BooleanField(default=False)
can_change = models.BooleanField(default=False)
can_delete = models.BooleanField(default=False)
It's unrelated to django-rules
but I would also recommend avoiding object_id
+ content_type
. You can do this in django with GenericForeignKey
s but you should leave them as a last resort. This article talks about the alternatives,