New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Access control based on wildcards #59
Comments
Is it supposed to be dynamic? I.e.
Should the wildcard-based control be dynamic, the User1 would already have the read access. Should it be static, the read permission would have to be assigned once again. In other words, the dynamic wildcard-based access control is resolved when calling "has_perm", and will probably require much more work to be done. The static access control means resolving the permission at the moment of calling |
Sounds ok to me. Plus, it's relatively easy to implement (seems like allowing obj to be sequence of particular model instance should be enough). Any takers for this one? I expect this to be properly tested and documented. |
@Halish Hi. I think I meant what you are calling the dynamic approach. That is: assign a permission to a wildcard, and all objects (current and future) which match that wildcard will be bound to that permission. It's not about batch-assigning permissions to a set of objects, but rather to check permissions based on a "rule". These rules could be easily changed, without changing lots of permission-related records on the background; because the wildcard is only checked/matched when the permission is checked. @lukaszb I probably won't be able to work on this for some more months... But I'm still very much interested and may be able to help someone interested in taking it forward (if not more, by providing and discussing ideas, and testing). |
@lukaszb I'm not really sure what you mean by sequence of particular model instance. If you mean to call the assign as:
then we would get static access, which in will be a shortcut for an iteration:
What I would do is create new classes ('d have to think it over): The wildcards permissions will be resolved at the moment of calling Do we agree at the design? |
Okey, seems I now got it right. I don't see easy way to do this - what rules are there going to be? Simple attributes equality/similarity checks? What else? I just don't see this task to be defined well enough. I need use cases. Now it seems to me that someone who really want such behavior can easily add some custom code over the guardian itself to achieve it. Remember that this is reusable app, it should help to solve general problems. Few questions:
Generally, I'm not into this one too much. Not before someone would give me good use cases and implementation example (can be abstract, should include API changes/additions and data model changes). PS. Guys, please make examples easy to read. What the fuck is a-42? User joe, class Post, object obj1/post1 and all is fine, really. |
True. I would argue that this feature is not that specific though. I see immediate application on a couple of projects that I'm involved with, and they're not that special. I want to write a better example, using code to illustrate a possible API for this. Hopefully I'll have some extra time next week to think about it.
I think we can split this in sub-goals. While a widget/form would be great, it probably involves a lot of work, and a code-side approach would already be very good. To offer the user the option to activate "rules" from a list that we have defined on the code-side would already be a good improvement. Like @Halish mentioned, the easiest way to implement may be to use regular django QuerySets to define the "rules". The widget/form may appear later, as a (very) simplified QuerySet editor, that would allow to express equality/similarity checks. But I definitely see that as a bonus... :)
Development in django-authority seems to have slowed down. There are some forks, but they also haven't been receiving a lot of attention. So, I've been avoiding it... even though, like you point out, it seems to address this issue. It seems to use a code-side approach only too. There may be other important differences to django-authority, but the lack of maintenance is enough for me to wish guardian itself to support wildcard/custom permissions too.
I see a connection, but I think that what we're discussing is a very different thing from what people usually call roles. I see roles as very similar to groups, with some differences: when people talk about groups, each user usually belongs to a single group and there's sometimes several levels (i.e., groups inside groups); When roles are used instead, users can belong to several roles simultaneously, but the roles are usually flat -- there's no hierarchy of roles. So, roles and groups are ways to handle sets of users when assigning permissions. They are handy when the current active users change frequently, so managing the permissions for them individually becomes a nuisance. We'd rather just assign them to a role (with all the permissions that come with it). The wildcards we are talking about, on the other hand, are a way to handle sets of objects when assigning permissions. They are useful when objects change frequently, and the permissions should be different depending on how they change. In this case, it's great if we can just define the rule that decides wich objects are accessible, and don't worry with permission assignment when the object changes. Now, I may be seeing the connection you were making (pls confirm if this is it)... What if instead of a role we would have just a "rule" that would "select" the set of users that should have permissions in a given scenario. For example, we may want to let premium users have access to "special" objects, that the free users can't have access to. We'd just have to create a rule that uses a "is_paying_user" field that we would have extended our User model with. If we also want to deny access to users that in spite of being "premium" have overdue payments, the rule could have that constraint too. This use case would also be very useful! Even though it wasn't what I was suggesting :)
I will try to provide some examples illustrated by code next week.
Sorry, will try to make the next ones simpler :) Thanks for listening. |
Hi. Here's the example I came up with. Please tell me what you think. In this (simplistic) example, the wildcard permissions allow users to modify only the blog posts that they authored, and that are still in draft. The model: from django.db import models
from django.contrib.auth.models import User
class Post(models.Model):
title = models.CharField(max_length=60)
body = models.TextField()
author = models.ForeignKey(User)
is_published = models.BooleanField(default=False) The views: from models import *
from django.http import HttpResponse
from guardian.models import *
def create_data(request):
jack = User.objects.create_user(
username='jack', email='jack@example.com', password='topsecretagentjack')
jack.save()
jane = User.objects.create_user(
username='jane', email='jane@example.com', password='topsecretagentjane')
jane.save()
post1 = Post.objects.create(
title='A first post', body='Contents...', author=jack)
post1.save()
post2 = Post.objects.create(
title='A second post', body='Contents...', author=jane)
post2.save()
post3 = Post.objects.create(
title='A third post', body='Contents...', author=jack, is_published=True)
post3.save()
# allow jack to change only the posts that he authored and that are still in draft
UserWildcardPermission.objects.assign('change_post',
user=jack,
mdl=Post,
objs=Post.objects.filter(author=jack).filter(is_published=False))
return HttpResponse("Data created!")
def try_access(request):
jack = User.objects.get(username='jack')
post1 = Post.objects.get(id=1)
post2 = Post.objects.get(id=2)
post3 = Post.objects.get(id=3)
assert(jack.has_perm('change_post', post1) == True)
assert(jack.has_perm('change_post', post2) == False)
assert(jack.has_perm('change_post', post3) == False)
return HttpResponse("Done") |
@filipefigcorreia It's really great, but I believe there's one more feature to be added.
I hope that made the case clearer. The real challenge here is storing the Also, it would be worth designing more general wildcard permissions, for granting permissions to owners. |
@Halish That's a good point. That last test is a bit more thorough. From what I understand, to persist a |
@filipefigcorreia Quick look here: https://github.com/django/django/blob/master/django/db/models/query.py#L33 reveals, that the @lukaszb The case I need it for is giving the 'edit' access only to the owner. As I mentioned earlier, I'm doing it on signals. It would be way easier though, if I could define it probably with fixtures. |
@Halish I was thinking we could store the raw sql command only (not the pickled object), as it'll probably avoid a lot of joins with the extra |
@filipefigcorreia I don't think that holding the raw SQL in the database is a good idea. In case of changing the database engine, there's a risk that the new database engine will not be able to process the SQL stored in the database. Also, when preparing the SQL for checking the permissions, we'll probably use only some parts of the queries, and not the whole raw SQL. I'll try to find some time to experiment a little in my own branch, and to design it well. |
Okey, not much discussion here. And best use case is some specific access for the owner of an object. This should be handled at the view explicitly in my view. Closing for now. |
This is an enhancement suggestion.
Guardian supports object based permissions, which allows a finer-grained control compared to what django does out-of-the-box. What I'd like to suggest is to support wildcards when choosing which objects to apply the permissions.
For example, instead of saying:
"User 1 has read access to object a-42 of the model MyClassA"
"User 1 has read access to object a-43 of the model MyClassA"
...
We could instead say:
"User 1 has read access to objects of the model MyClassA that match the condition first_name = 'Jhon'"
...
I.e., let "User 1" read all objects with a "first_name" attribute with the value "Jhon".
Edit: Removed reference to Attribute-based access control, which is not what I meant at all.
The text was updated successfully, but these errors were encountered: