0

我必须管理权限并且我有不同的用户类型,例如这里的一对。

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

但这不起作用,理想情况下,我想为传入的所有类调用方法并执行 or (with any)。

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

理论上,我什至可以只为每个角色使用字典,但我喜欢默认为 false 的技巧,有时我还需要一个函数来计算权限。

有什么建议么?

4

2 回答 2

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它们并与它们一起操作来完成你想要做的事情。

于 2013-02-09T20:51:51.127 回答
0

这是一个替代答案,它使用多重继承和属性来大大简化实现(因为,再一次,你本质上是在重新发明轮子)。它完全消除了在类中具有roles属性的需要MultiRoleUser,以及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
于 2013-02-10T20:56:19.897 回答