通过继承智能地处理不同的权限

时间:2013-02-09 11:08:06

标签: python permissions getattr

我必须管理权限,我有不同的用户类型,至于 例如,一对夫妇。

def not_allowed(*args, **kwargs): return False

class User(object):
    def __init__(self, userid):
        self.userid = userid

    def __getattr__(self, attr):
        return not_allowed

    def view_profile(self)
        return True


class Admin(User):
    def edit_comment(self):
        return True

class Expert(User):
    def delete_post(self):
        return True


user = {'userid': 'user', 'roles': ['admin', 'expert']}

现在我希望能够拥有MultiRole类型,理论上应该这样 只需能够完成其角色能够做的所有事情。

我试过这样的事情:

class MultiRoleUser(User):
    """A multirole user has all the power of all the roles together
    """
    def __init__(self, userid, roles):
        super(MultiRoleUser, self).__init__(userid)
        self.roles = roles

    def __getattr__(self, attr):
        all_funcs = [getattr(x, attr) for x in self.roles]
        return any(x() for x in all_funcs)

哪个应该用作

u = MultiRoleUser('userid', [Admin, Expert])

但它不起作用,理想情况下我想为所有人调用这些方法 传入的类并执行或(使用任何)。

问题是要调用我需要的对象的方法 那个类型..

理论上我甚至可能只为每个角色使用字典, 但我喜欢默认的假伎俩,有时候我 还需要一个计算权限的函数。

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

虽然我倾向于同意您可能不想重新发明轮子,但下面是您的尝试版本,似乎可以使用AFAIK。

基本上,我首先通过从object派生它们来切换到显式的新式类,以便super()调用可以工作,然后我改变了self.roles = roles初始化在MultiRoleUser类中创建所需的实例。最后,我更改了MultiRoleUser.__getattr__()如何使用它们来处理没有搜索权限属性的角色类。

def not_allowed(*args, **kwargs): return False

class User(object):
    def __init__(self, userid):
        self.userid = userid

    def __getattr__(self, attr):
        return not_allowed

    def view_profile(self):
        return True

class Admin(User):
    def edit_comment(self):
        return True

class Expert(User):
    def delete_post(self):
        return True

class MultiRoleUser(User):
    """A multirole user has all the power of all the roles together"""
    def __init__(self, userid, roles):
        super(MultiRoleUser, self).__init__(userid)
        self.roles = [role(userid) for role in roles] # create instances needed

    def __getattr__(self, attr):
        all_funcs = [getattr(x, attr, None) for x in self.roles]
        return any(x() for x in all_funcs if x) # check permission if there was one

u = MultiRoleUser('userid', [Admin, Expert])

print 'u.edit_comment:', u.edit_comment
print 'u.delete_post:', u.delete_post
顺便说一下,我认为一个更好的Python实现会使用sets和它们的操作来完成你想要做的事情。

答案 1 :(得分:0)

这是一个替代答案,它使用多个继承和属性来极大地简化实现(因为,再一次,你基本上是重新发明轮子)。它完全消除了在roles类中使用MultiRoleUser属性的必要性,以及使用它所需的专用getattr()方法。

使用多重继承的想法发生在我身上,因为将class MultiRoleUser定义为拥有多个User子类实例似乎很奇怪,而不只是是< / em>一个人。使用属性的想法是考虑到这样一个事实,即类gettattr()所需的类是调用找到的函数属性来获取它们的值,这是什么的一部分属性都是关于。

class User(object):
    def __init__(self, userid):
        self.userid = userid

    def __getattr__(self, attr):  # unknown/undefined permission
        return False

    @property
    def view_profile(self):
        return True

class Admin(User):
    @property
    def edit_comment(self):
        return True

class Expert(User):
    @property
    def delete_post(self):
        return True

def multi_role_user(cls_name, *roles):
    """Factory function to create a multirole user class which has the combined
       power of all the User subclasses given"""
    if not roles:
        raise TypeError('at least one subclass of class User must be specified')
    if not all(issubclass(role, User) for role in roles):
        raise TypeError('all roles must be subclasses of class User')
    return type(cls_name, roles, {})

MultiRoleUser = multi_role_user('MultiRoleUser', Admin, Expert)
u = MultiRoleUser('my_userid')

print 'u.userid:', u.userid
print 'u.view_profile:', u.view_profile
print 'u.edit_comment:', u.edit_comment
print 'u.delete_post:', u.delete_post
print 'u.can_spam:', u.can_spam