|
|
@ -7,6 +7,7 @@ from typing import Optional, List, Set, Dict |
|
|
|
class Role(Enum): |
|
|
|
"""User role definitions.""" |
|
|
|
|
|
|
|
OWNER = 'OWNER' |
|
|
|
ADMIN = 'ADMIN' |
|
|
|
AUDITOR = 'AUDITOR' |
|
|
|
MODERATOR = 'MODERATOR' |
|
|
@ -14,39 +15,48 @@ class Role(Enum): |
|
|
|
ANONYMOUS = 'ANONYMOUS' |
|
|
|
NONE = 'NONE' |
|
|
|
|
|
|
|
def __str__(self): |
|
|
|
return self.value |
|
|
|
|
|
|
|
|
|
|
|
class RoleTree(defaultdict): |
|
|
|
"""Simple tree structure to handle hierarchy.""" |
|
|
|
|
|
|
|
def __call__(self, data: Role) -> 'RoleTree': |
|
|
|
def __call__(self, data: Role, power: int) -> 'RoleTree': |
|
|
|
"""Handle direct calls to the tree.""" |
|
|
|
return RoleTree(self, data) |
|
|
|
return RoleTree(self, data, power) |
|
|
|
|
|
|
|
# def __hash__(self): |
|
|
|
parent: Optional['RoleTree'] |
|
|
|
data: Role |
|
|
|
power: int |
|
|
|
roles: Dict[Role, List['RoleTree']] |
|
|
|
|
|
|
|
def __init__( |
|
|
|
self, |
|
|
|
parent: Optional['RoleTree'], |
|
|
|
data: Role, |
|
|
|
power: int = None, |
|
|
|
**kwargs: dict) -> None: |
|
|
|
"""Configure a RoleTree.""" |
|
|
|
super().__init__(**kwargs) |
|
|
|
self.parent: Optional[RoleTree] = parent |
|
|
|
self.data: Role = data |
|
|
|
self.power: int = power if power is not None else 1 |
|
|
|
self.default_factory = self # type: ignore |
|
|
|
self.roles: Dict[Role, List[RoleTree]] = {data: [self]} |
|
|
|
|
|
|
|
def populate( |
|
|
|
self, children: Dict[Role, Optional[dict]]) -> List['RoleTree']: |
|
|
|
"""Populate a RoleTree from a dictionary of a Role hierarchy.""" |
|
|
|
role_list: List[RoleTree] = [] |
|
|
|
role_list: List[RoleTree] = [self] |
|
|
|
for child_role in children.keys(): |
|
|
|
element = children[child_role] |
|
|
|
new_node = self(child_role) |
|
|
|
new_node = self(child_role, self.power + 1) |
|
|
|
if isinstance(element, dict) and element: |
|
|
|
role_list += new_node.populate(element) |
|
|
|
role_list.extend(new_node.populate(element)) |
|
|
|
else: |
|
|
|
role_list.append(new_node) |
|
|
|
self[child_role] = new_node |
|
|
|
role_list.append(new_node) |
|
|
|
for role_tree in role_list: |
|
|
|
if role_tree.data not in self.roles.keys(): |
|
|
|
self.roles[role_tree.data] = [] |
|
|
@ -94,15 +104,22 @@ class RoleTree(defaultdict): |
|
|
|
roles.extend(role_tree.get_children_roles()) |
|
|
|
return set(roles) |
|
|
|
|
|
|
|
|
|
|
|
ROLES = RoleTree(None, Role.ADMIN) |
|
|
|
ROLES.populate({ |
|
|
|
Role.MODERATOR: { |
|
|
|
Role.USER: { |
|
|
|
Role.ANONYMOUS: None |
|
|
|
def __str__(self): |
|
|
|
return str(self.data) |
|
|
|
|
|
|
|
|
|
|
|
ROLES = RoleTree(None, Role.OWNER, 0) |
|
|
|
ROLE_LIST = sorted( |
|
|
|
ROLES.populate({ |
|
|
|
Role.ADMIN: { |
|
|
|
Role.MODERATOR: { |
|
|
|
Role.USER: { |
|
|
|
Role.ANONYMOUS: None |
|
|
|
} |
|
|
|
}, |
|
|
|
Role.AUDITOR: { |
|
|
|
Role.USER: None |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
Role.AUDITOR: { |
|
|
|
Role.USER: None |
|
|
|
} |
|
|
|
}) |
|
|
|
}), |
|
|
|
key=lambda rt: rt.power) |