-
Notifications
You must be signed in to change notification settings - Fork 14
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
Consider adding some form of user group support #16
Comments
I thought about this a bit more, and I really like the Consider this set of class Permission(object):
def pre_validate(method, model, user=None):
return True
def post_validate(method, instance, user=None):
return True
class PermissionEveryone(Permission):
pass
class PermissionAdmin(Permission):
def __init__(self, admin_property):
self.admin_property = admin_property
def _user_is_admin(self, user):
# use self.admin_property to determine if user is admin
def pre_validate(method, model, user=None):
return self._user_is_admin(user)
def post_validate(method, instance, user=None):
return self._user_is_admin(user)
class PermissionUser(Permission):
def pre_validate(method, model, user=None):
return user is not None
def post_validate(method, instance, user=None):
return user is not None
class PermissionOwner(Permission):
def __init__(self, owner_property):
self.owner_property = owner_property
def post_validate(method, instance, user=None):
# use self.owner_property to determine if user is owner When assigning permissions, instead of saying this: permissions={
'GET': PERMISSION_ANYONE,
'POST': PERMISSION_LOGGED_IN_USER,
'PUT': PERMISSION_OWNER_USER,
'DELETE': PERMISSION_ADMIN
}, We'd say it this way: permissions={
'GET': [PermissionAnyone()],
'POST': [PermissionUser()],
'PUT': [PermissionOwner('owner'), PermissionAdmin('is_admin')],
'DELETE': [PermissionAdmin('is_admin')]
}, In This allows us to define permissions like this: class PermissionGroup(Permission):
def __init__(self, group_property, *groups):
self.group_property = group_property
self.groups = set(groups)
def post_validate(method, instance, user=None):
# check the self.group_property of user to see if
# any of the groups match self.groups We'd then give our custom user class a groups property, and define permissions like this: author_permissions = [PermissionGroup('groups', 'Editor', 'Author'), PermissionOwner('owner'), PermissionAdmin('is_admin')]
# ... snip ...
permissions={
'GET': [PermissionAnyone()],
'POST': author_permissions,
'PUT': author_permissions,
'DELETE': author_permissions
}, And suddenly we have the beginnings of a group system. This could even be fully backwards compatible with the existing permissions API by defining There may still be flaws with this approach, but it seems like a pretty good idea to me so far. |
Nice!!!!!
|
|
Another concern: This permissions system concept doesn't address how we'd filter requests for all instances of a given model that a user is allowed to access. If a user does a This will definitely require some more thought. |
Okay, here's my proposed solution to this: http://paste.debian.net/82594/ This is a collection of permission classes. Note that Also note that there is a The workflow would look like this:
An important take-away from this is that the order the permissions are listed is important. A user would typically want I've also changed where the admin and owner property names come from. The constructor args for these classes are used to look up the property name in RESTMeta. If all of that were implemented as described, backward compatibility would be as easy as this: PERMISSION_ANYONE = [PermissionEveryone()]
PERMISSION_LOGGED_IN_USER = [PermissionUser()]
PERMISSION_OWNER_USER = [PermissionAdmin('admin_property'), PermissionOwner('user_owner_property')]
PERMISSION_ADMIN = [PermissionAdmin('admin_property')] None of that code is tested. I'm just getting ideas down. I'll probably start on that implementation sometime within the next 24 hours. |
I have a branch with this implemented, but it depends on #15 being merged first. |
Currently, our permission system has the following types of permission for a given operation on a given model:
This means that there is currently no built-in way to, for example, grant one non-admin user the ability to create an instance of a given model, but deny another non-admin user the same permission.
It would be possible for a rest_gae user to implement their own group system using a custom user model, and tying into the callbacks we provide. We may decide that this is acceptable, and any direct support for groups is out of scope for this project. In that case, this issue can be closed with no action taken.
It would also be possible to add some set of features that would either fully implement a working group system, or make it easier to implement one.
Here are some features that a user would expect of a full group system:
PERMISSION_GROUP['foo', 'bar']
Here are some features that, if implemented, would ease user development of a group system, without actually implementing one:
PERMISSION_CUSTOM
permission that would result in a callback to decide if permission is granted to access an object. Not sure how this would work with building queries.Permission
base class that is used instead of constants. Each existing permission would subclassPermission
, and we'd move some logic into it's methods. Users would provide their own subclasses. This would be an alternative to using callbacks. I haven't thought this one through, so I don't know what the implementation would look like.The text was updated successfully, but these errors were encountered: