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



我必须管理权限,并且我有不同的用户类型,例如举一对夫妇的例子。

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])

但它不起作用,理想情况下,我想调用所有的方法传入的类执行a或(与任意类一起)。

问题是,要调用方法,我需要有一个那种。。

理论上,我甚至可以为每个角色使用一本字典,但我喜欢默认为假的把戏,有时我还需要一个函数来计算权限。

有什么建议吗?

尽管我倾向于同意你可能不想在这方面重新发明轮子,但下面是你的尝试的版本,它似乎可以在AFAIK中工作。

基本上,我首先必须切换到显式的新型类,使它们从object派生,以便super()调用能够工作,然后,我更改了MultiRoleUser类中的self.roles = roles初始化,以创建所需的实例。最后,我更改了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及其操作来完成您想要做的事情

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

我想到了使用多重继承的想法,因为将class MultiRoleUser定义为具有多个User子类实例的,而不仅仅是本身是一个,这似乎很奇怪。使用属性的想法源于这样一个事实,即类所需的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

最新更新