I have a 5 types of users:

  1. Admin     (permissions ALL)
  2. Creator   (permissions "v", "a", "m", "c")
  3. Manager (permissions "v", "a", "m")
  4. Analyst   (permissions "v", "a")
  5. Viewer    (permissions "v")

This is a hierarchical setup where each user has the permissions of each preceding user. To set this up in my project, I can easily write:

class RootFactory(object):

    __acl__ = [ 
        (Allow, '__ADMIN__', ALL_PERMISSIONS),
        (Allow, 'creator',  ('VIEWER', 'ANALYST', 'MANAGER', 'CREATOR')),
        (Allow, 'manager',  ('VIEWER', 'ANALYST', 'MANAGER')),
        (Allow, 'analyst',  ('VIEWER', 'ANALYST')),
        (Allow, 'viewer',   ('VIEWER')),
        (Allow, Everyone, NO_PERMISSION_REQUIRED) 
    ]

    def __init__(self, request):
        self.request = request

Then, in my views.py, for example, I do:

@view_config(route_name='mgmt_handler', renderer='manage.jinja2', permission='MANAGER')
def mgmt_handler(request):
    pass  # do stuff

This works nicely for most instances. However, I am not sure of how to best accomplish the following:

  • How do I make this access control more "fine-grained" by allowing user1, a viewer, to have certain higher permissions on an as needed basis? Does this fall under the realm of "object-level" security? For the most part, the global root factory will suffice, but how can I accommodate those cases where a low-tier user is granted a higher permission, or when a high-tier user is denied a lower permission?

  • Is there a way to conveniently determine the principles of a particular user so that in my view I can say something to the effect of: if user.principle in list_of_permissions: do something...? Or, is this simply another query from the database, where the user's groups are stored?

Case and point, my goal is to have a flexible, hierarchical permission system. What is the most effective way to do this? The tutorials I've read only address more simple, global policies (which I do understand.) Part of my problem is how to a comprehensive understanding of object/instance-level security.

Thanks for the help.

有帮助吗?

解决方案

I'm not sure I clearly get what you want to achieve. As I understood, you have a handful of user groups with common permissions for each object in the system, and going to tune access to a particular object for a particular user. For example, owner of an object has all permissions for the object regardless of owner's user group.

Firstly, you should use a hierarchy of location-aware resources. In this way you can keep default permissions in the root resource and tune them in the child one:

class RootFactory(object):

    __name__ = ''
    __parent__ = None
    __acl__ = [ 
        (Allow, '__ADMIN__', ALL_PERMISSIONS),
        (Allow, 'creator',  ('VIEWER', 'ANALYST', 'MANAGER', 'CREATOR')),
        (Allow, 'manager',  ('VIEWER', 'ANALYST', 'MANAGER')),
        (Allow, 'analyst',  ('VIEWER', 'ANALYST')),
        (Allow, 'viewer',   ('VIEWER')),
        # (Allow, Everyone, NO_PERMISSION_REQUIRED) 
        # It seems, here you want to deny access for all other users, 
        # so you should use this:
        # (Deny, Everyone, ALL_PERMISSIONS)
        # or simply:
        DENY_ALL
    ]

    def __init__(self, request):
        self.request = request

    def __getitem__(self, name):
        return ChildObject(name, self)

Then in the child object constructor, you can add a special permissions for this particular object:

class ChileObject(object):

    def __init__(self, request, name, parent):
        self.__parent__ = parent
        self.__name__ = name
        # Do some stuff, for example loading object from DB 
        # and populate other attributes of the object.
        # Then add permission for the object's owner
        self.__acl__ = [(Allow, self.owner_id, ALL_PERMISSIONS)]

The result ACL will be merged version of root's ACL and child's one, i.e:

[ 
    (Allow, self.owner_id, ALL_PERMISSIONS),
    (Allow, '__ADMIN__', ALL_PERMISSIONS),
    (Allow, 'creator',  ('VIEWER', 'ANALYST', 'MANAGER', 'CREATOR')),
    (Allow, 'manager',  ('VIEWER', 'ANALYST', 'MANAGER')),
    (Allow, 'analyst',  ('VIEWER', 'ANALYST')),
    (Allow, 'viewer',   ('VIEWER')),
    DENY_ALL 
]

As for your second question, you can find a useful functions for checking permissions in the pyramid.security module.

其他提示

Most permission systems have both users and groups. If you added groups to your situation, you could create a separate group that adds the permissions you want, and then add the users you want to have these permissions. You can add and remove a user from a group as needed.

You could also build in exceptions to resources. For example you could add a list of users to a resource who are allowed to modify it regardless of what other permissions they might have.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top