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) を実行したいと考えています。

問題は、そのタイプのオブジェクトが必要なメソッドを呼び出すことです..

理論的には、代わりに各ロールに辞書を使用することもできますが、デフォルトの偽のトリックが好きで、パーミッションを計算する関数も必要になる場合があります。

助言がありますか?

4

2 に答える 2

1

Although I tend to agree that you probably don't want to reinvent the wheel on this, below is version of your attempt that appears to work AFAIK.

Basically, I first I had switch to explicit new-style classes by making them derived from object so that the super() call would work, then second, I changed the self.roles = roles initialization in the MultiRoleUser class to create the instances needed. Lastly I changed how the MultiRoleUser.__getattr__()used them to handle role classes that didn't have the sought permission attribute.

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

BTW, I think a better Python implementation would use sets and operations with them to accomplish what you're trying to do.

于 2013-02-09T20:51:51.127 に答える
0

複数の継承とプロパティを使用して実装を大幅に簡素化する代替の回答を次に示します (繰り返しますが、本質的に車輪を再発明していたためです)。rolesクラスに属性を持つ必要がなく、それを使用するために必要なMultiRoleUser特殊なメソッドも完全に排除されます。getattr()

多重継承を使用するというアイデアが思い浮かんだのは、サブクラスのインスタンスが1 つだけではなく、複数のインスタンスをclass MultiRoleUser持つ定義するのが奇妙に思えたからです。プロパティを使用するというアイデアは、クラスが必要とするクラスが、見つかった関数属性を呼び出してその値を取得するという事実を考えた結果として生まれました。これは、プロパティとは何かの一部です。Usergettattr()

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 に答える