import json
class PermissionsConfiguration():
def __init__(self, is_registration_required=True):
if type(is_registration_required) != bool:
raise TypeError((
"'is_registration_required' argument during instance creattion "
"must be of boolean type"
" - '%s' (%s) detected"
) % (is_registration_required, type(is_registration_required)))
else:
self.__roles = set()
self.__users = set()
self.__actions = set()
self.__conditions = set()
self.__privileges = dict(
for_users=dict(),
for_roles=dict(),
)
self.__options = dict(
is_registration_required=is_registration_required
)
###############################################################
###############################################################
# dump and load
###############################################################
###############################################################
def dumps(self):
return json.dumps(dict(
roles=list(self.__roles),
users=list(self.__users),
actions=list(self.__actions),
conditions=list(self.__conditions),
privileges=self.__privileges,
options=self.__options,
))
def loads(self, dump_string):
try:
dump_dict = json.loads(dump_string)
except ValueError as error:
error.args = ("Invalid JSON format of dump_string",)
raise
else:
# keep a backup of current state before starting to mangle the current state with __load()
backup_dump_dict = json.loads(self.dumps())
try:
self.__load(dump_dict)
except KeyError as error:
self.__load(backup_dump_dict)
raise
def __load(self, dump_dict):
self.__roles = set(dump_dict.pop("roles"))
self.__users = set(dump_dict.pop("users"))
self.__actions = set(dump_dict.pop("actions"))
self.__conditions = set(dump_dict.pop("conditions"))
self.__privileges = dump_dict.pop("privileges")
self.__options = dump_dict.pop("options")
if len(dump_dict) > 0:
raise KeyError("Unknown keys %s found in dump dictionary" % dump_dict.keys())
###############################################################
###############################################################
# registrations
###############################################################
###############################################################
def is_registration_required(self, is_registration_required=None):
if is_registration_required != None:
# set a boolean value
if type(is_registration_required) != bool:
raise TypeError((
"'is_registration_required' argument must be of boolean type"
" - '%s' (%s) detected"
) % (is_registration_required, type(is_registration_required)))
else:
self.__options['is_registration_required'] = is_registration_required
else:
# return the current value
return self.__options['is_registration_required']
def register_roles(self, *args):
for index, a_role in enumerate(args):
if type(a_role) != str:
raise TypeError((
"%dth role (%s) for registering roles must be a string - '%s' detected"
) % (index, a_role, type(a_role)))
else:
self.__roles.add(a_role)
def register_users(self, *args):
for index, a_user in enumerate(args):
if type(a_user) != str:
raise TypeError((
"%dth user (%s) for registering users must be a string - '%s' detected"
) % (index, a_user, type(a_user)))
else:
self.__users.add(a_user)
def register_actions(self, *args):
for index, an_action in enumerate(args):
if type(an_action) != str:
raise TypeError((
"%dth action (%s) for registering actions must be a string - '%s' detected"
) % (index, an_action, type(an_action)))
else:
self.__actions.add(an_action)
def register_conditions(self, *args):
for index, a_condition in enumerate(args):
if type(a_condition) != str:
raise TypeError((
"%dth condition (%s) for registering conditions must be a string - '%s' detected"
) % (index, a_condition, type(a_condition)))
else:
self.__conditions.add(a_condition)
###############################################################
###############################################################
# assigning privileges
###############################################################
###############################################################
def assign_privilege_for_a_role(self, a_role, an_action, is_allowed_or_condition):
self.__validate_parameters(
a_role=a_role, an_action=an_action, is_allowed_or_condition=is_allowed_or_condition
)
self.__privileges['for_roles'].setdefault(a_role, dict())
self.__privileges['for_roles'][a_role][an_action] = is_allowed_or_condition
def assign_privilege_for_a_user(self, a_user, an_action, is_allowed_or_condition):
self.__validate_parameters(
a_user=a_user, an_action=an_action, is_allowed_or_condition=is_allowed_or_condition
)
self.__privileges['for_users'].setdefault(a_user, dict())
self.__privileges['for_users'][a_user][an_action] = is_allowed_or_condition
def __validate_parameters(self,
a_role=None, a_user=None, an_action=None, is_allowed_or_condition=None
):
if self.is_registration_required():
if a_role and (a_role not in list(self.__roles)):
raise LookupError("Role '%s' is not yet registered in this configuration" % a_role)
if a_user and (a_user not in list(self.__users)):
raise LookupError("User '%s' is not yet registered in this configuration" % a_user)
if an_action and (an_action not in list(self.__actions)):
raise LookupError("Action '%s' is not yet registered in this configuration" % an_action)
if is_allowed_or_condition:
if type(is_allowed_or_condition) != bool:
if self.is_registration_required():
if is_allowed_or_condition not in list(self.__conditions):
raise LookupError((
"Condition '%s' is not yet registered in this configuration"
" - must use a boolean or a registered condition."
) % (is_allowed_or_condition))
###############################################################
###############################################################
# determining privileges
###############################################################
###############################################################
def is_allowed(self, invoker_role, invoker_user, requested_action):
# may return boolean True/False or a string Condition
# if a speific condition is attached
# to the user/role for the requested action
try:
return self.__privileges['for_users'][invoker_user][requested_action]
except KeyError:
try:
return self.__privileges['for_roles'][invoker_role][requested_action]
except KeyError:
return False