2013-02-09 5 views
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']} 

는 지금은 이론적으로 단순히 역할을 할 수있는 모든 것을 할 수 있어야 다목적 유형을 가질 수 있어야합니다.

는이 같은 뭔가 시도 :

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

표기하지만 이상적으로 나는 모든 클래스의 메소드를 호출하고 싶습니다 작동하지 않습니다

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) 

전달 및 할 또는 (함께).

문제는 내가 심지어 단지, 대신 각 역할에 대해 을 사전을 사용할 수있는 내가 해당 유형의 객체를 가질 필요가 방법 .. 이론적으로

전화를하지만 false로 기본을 좋아하다 트릭, 그리고 때로는 내가 또한 권한을 계산하는 함수가 필요합니다.

제안 사항?

+0

왜 처음부터 자신의 인증 프레임 워크를 사용하고 있습니까?이것은 해결 된 문제이며 휠을 재발 명하지 못하도록 충분히 견고하고 균일합니다. – delnan

+0

지금은 선택의 여지가 없기 때문에 API를 병에 넣고 추가로 통합 할 것을 제안합니다. 어쨌든이 마지막 일이 끝나면 60 줄의 코드로 잘될 것입니다. –

답변

1

나는 AFAIK를 사용하는 것으로 보이는 시도의 버전을 아래에서 설명 하겠지만 동의하지 않는 경향이 있습니다.

기본적으로, 내가 먼저 내가 super() 호출 초 후, 작동 할 수 있도록 그들을 object에서 파생하여 명시 적으로 새로운 스타일의 클래스로 전환했다, 내가 필요한 인스턴스를 만들 수 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 

은 BTW, 나는 더 나은 파이썬 구현 당신이 뭘 하려는지 달성하기 위해 그들과 함께 sets 및 운영을 사용합니다 생각합니다.

+0

확인 코드에 몇 가지 실수가있었습니다. 1. 실제 코드에서 이미 새 스타일 클래스를 사용하고있었습니다. 2. 나는 "userid"를 전달해야하므로 role()이 작동하지 않는다는 것을 의미하는 Admin an Expert에서 상속이 필요합니다. 감사합니다. –

+0

좋아요, 질문에있는 수정 된 코드의 내용을 제 대답에 추가했습니다. 변경 사항에 대한 다른 제안이 작동한다는 사실을 바꾸지 않습니다. – martineau

0

복수 상속 및 속성을 사용하여 을 크게 변경하면은 구현을 단순화합니다 (다시 한번 말하지만 본질적으로 바퀴를 다시 발명했기 때문에). MultiRoleUser 클래스에 roles 속성을 가질 필요가 없으며이를 사용하는 데 특수화 된 getattr() 메서드가 필요하지 않습니다. 이 User sublclasses의 class MultiRoleUser로 가진 여러 인스턴스를 정의하는 이상한 것 같았다 때문에

다중 상속을 사용하는 아이디어는 오히려 단지 하나의 자신을 것보다, 나에게 발생했습니다. 속성을 사용하는 아이디어는 클래스에 필요한 클래스 이라고하는 사실에 대해 생각한 결과였습니다.이 속성은 값을 얻기 위해 발견되었습니다. 속성은 모든 속성에 대한 것입니다.

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 
+0

멋지긴하지만 서로 다른 역할을 조합 할 수있는 클래스를 생성하고 싶지 않으므로 클래스를 동적으로 생성해야합니다. 잘 모르겠습니다. –

+0

아, 동적으로 생성 할 수 있습니다. 원한다면 다른 하위 클래스를 작성하는 방법을 설명하기 위해 답변을 업데이트했습니다. 추가 된 팩토리 기능의 대부분은 오류 검사입니다. – martineau

관련 문제