def clean(self): try: get_roleclass(self.role_class) except RoleNotFound: raise ValidationError({ 'role_class': 'This string representation does not exist as a Role class.' })
def has_permission(user, permission, obj=None): """ Return True if the "user" has the "permission". """ perm_obj = string_to_permission(permission) if obj: stack = list() stack.append(obj) while stack: # Getting the dictionary of permissions # from the cache. current_obj = stack.pop(0) roles_list = get_from_cache(user, current_obj) for role_s, perm_list in roles_list: # Check for permissions. for perm_tuple in perm_list: if perm_tuple[0] == perm_obj.id: return perm_tuple[1] # Now, we are in inherit mode. # We need to check if the Role # allows the inherit. return inherit_check(get_roleclass(role_s), permission) # Try to look even further # for possible parent fields. parents_list = get_parents(current_obj) for parent in parents_list: stack.append(parent) # If nothing was found or the obj was # not provided, try now for roles with # "models" = ALL_MODELS. roles_list = get_from_cache(user) for role_s, perm_list in roles_list: # Check for permissions. for perm_tuple in perm_list: if perm_tuple[0] == perm_obj.id: return perm_tuple[1] # Now, we are in inherit mode. # We need to check if the Role # allows the inherit. return inherit_check(get_roleclass(role_s), permission) # If all fails and the user does not have # a role class with "ALL_MODELS", we finnaly # deny the permission. return False
def __str__(self): role = get_roleclass(self.role_class) output = '{user} is {role}'.format(user=self.user, role=role.get_verbose_name()) if self.obj: output += ' of {obj}'.format(obj=self.obj) return output
def assign_permission(user, role_class, permission, access, obj=None): """ Assign a specific permission value to a given UserRole instance. The values used in this method overrides any configuration of "allow/deny" or "inherit_allow/inherit_deny". """ role = get_roleclass(role_class) perm = string_to_permission(permission) query = UserRole.objects.filter(user=user, role_class=role.get_class_name()) if obj: ct_obj = ContentType.objects.get_for_model(obj) query = query.filter(content_type=ct_obj.id, object_id=obj.id) if not query: raise InvalidPermissionAssignment('No Role instance was affected.') for role_obj in query: perm_obj, created = RolePermission.objects.get_or_create( # pylint: disable=W0612 role=role_obj, permission=perm) perm_obj.access = bool(access) perm_obj.save() # Cleaning the cache system. delete_from_cache(user, role_obj.obj)
def remove_all(role_class=None, obj=None): """ Remove all roles of the project. If "role_class" is provided, only the roles of "role_class" will be affected. If "obj" is provided, only users for that object will lose the role. """ query = UserRole.objects.all() role = None if role_class: # Filtering by role class. role = get_roleclass(role_class) query = UserRole.objects.filter(role_class=role.get_class_name()) if obj: # Filtering by object. ct_obj = ContentType.objects.get_for_model(obj) query = query.filter(content_type=ct_obj.id, object_id=obj.id) # Check if object belongs # to the role class. check_my_model(role, obj) # Cleaning the cache system. for role_obj in query: delete_from_cache(role_obj.user, role_obj.obj) # Cleaning the database. role_obj.delete()
def remove_roles(users_list, role_class=None, obj=None): """ Delete all RolePermission objects in the database referencing the followling role_class to the user. If "obj" is provided, only the instances refencing this object will be deleted. """ query = UserRole.objects.filter(user__in=users_list) role = None if role_class: # Filtering by role class. role = get_roleclass(role_class) query = query.filter(role_class=role.get_class_name()) if obj: # Filtering by object. ct_obj = ContentType.objects.get_for_model(obj) query = query.filter(content_type=ct_obj.id, object_id=obj.id) # Check if object belongs # to the role class. check_my_model(role, obj) # Cleaning the cache system. for user in users_list: delete_from_cache(user, obj) # Cleaning the database. query.delete()
def has_role(user, role_class=None, obj=None): """ Check if the "user" has any role attached to him. If "role_class" is provided, only this role class will be counted. If "obj" is provided, the search is refined to look only at that object. """ query = UserRole.objects.filter(user=user) role = None if role_class: # Filtering by role class. role = get_roleclass(role_class) query = query.filter(role_class=role.get_class_name(), user=user) if obj: # Filtering by object. ct_obj = ContentType.objects.get_for_model(obj) query = query.filter(content_type=ct_obj.id, object_id=obj.id) # Check if object belongs # to the role class. check_my_model(role, obj) return query.count() > 0
def get_objects(user, role_class=None, model=None): """ Return the list of objects attached to a given user. If "role_class" is provided, only the objects which as registered in that role class will be returned. If "model" is provided, only the objects of that model will be returned. """ query = UserRole.objects.filter(user=user) role = None if role_class: # Filtering by role class. role = get_roleclass(role_class) query = query.filter(role_class=role.get_class_name()) if model: # Filtering by model. ct_obj = ContentType.objects.get_for_model(model) query = query.filter(content_type=ct_obj.id) # Check if object belongs # to the role class. check_my_model(role, model) # TODO result = set(ur_obj.obj for ur_obj in query) # TODO return list(result)
def get_users(role_class=None, obj=None): """ If "role_class" and "obj" is provided, returns a QuerySet of users who has this role class attached to the object. If only "role_class" is provided, returns a QuerySet of users who has this role class attached to any object. If neither "role_class" or "obj" are provided, returns all users of the project. """ role = None kwargs = {} if role_class: # All users who have "role_class" attached to any object. role = get_roleclass(role_class) kwargs['roles__role_class'] = role.get_class_name() if obj: # All users who have any role attached to the object. ct_obj = ContentType.objects.get_for_model(obj) kwargs['roles__content_type'] = ct_obj.id kwargs['roles__object_id'] = obj.id # Check if object belongs # to the role class. check_my_model(role, obj) # Return as a distinct QuerySet. return get_user_model().objects.filter(**kwargs).distinct()
def test_exceptions(self): """ test all exceptions on utils module """ with self.assertRaises(RoleNotFound): get_roleclass(12345) with self.assertRaises(RoleNotFound): get_roleclass('I am not a role.') self.assertEqual(get_model('I am not a model.'), None) self.assertEqual(get_parents(FakeModel1), []) with self.assertRaises(ParentNotFound): get_parents(FakeModel2) with self.assertRaises(ImproperlyConfigured): is_unique_together(FakeModel3)
def assign_roles(users_list, role_class, obj=None): """ Create a RolePermission object in the database referencing the followling role_class to the user. """ users_set = set(users_list) role = get_roleclass(role_class) name = role.get_verbose_name() # Check if object belongs # to the role class. check_my_model(role, obj) # If no object is provided but the role needs specific models. if not obj and role.models != ALL_MODELS: raise InvalidRoleAssignment( 'The role "%s" must be assigned with a object.' % name) # If a object is provided but the role does not needs a object. if obj and role.models == ALL_MODELS: raise InvalidRoleAssignment( 'The role "%s" must not be assigned with a object.' % name) # Check if the model accepts multiple roles # attached using the same User instance. if obj and is_unique_together(obj): for user in users_set: has_user = get_roles(user=user, obj=obj) if has_user: raise InvalidRoleAssignment( 'The user "%s" already has a role attached ' 'to the object "%s".' % (user, obj)) if role.unique is True: # If the role is marked as unique but multiple users are provided. if len(users_list) > 1: raise InvalidRoleAssignment( 'Multiple users were provided using "%s", ' 'but it is marked as unique.' % name) # If the role is marked as unique but already has an user attached. has_user = get_users(role_class=role, obj=obj) if has_user: raise InvalidRoleAssignment( 'The object "%s" already has a "%s" attached ' 'and it is marked as unique.' % (obj, name)) for user in users_set: ur_instance = UserRole(role_class=role.get_class_name(), user=user) if obj: ur_instance.obj = obj ur_instance.save() # Cleaning the cache system. delete_from_cache(user, obj)
def get_user(role_class=None, obj=None): """ Get the User instance attached to the object. Only one UserRole must exists and this relation must be unique=True. Returns None if there is no user attached to the object. """ query = UserRole.objects.select_related('user').all() role = None if role_class: # All users who have "role_class" attached to any object. role = get_roleclass(role_class) query = query.filter(role_class=role.get_class_name()) if obj: # All users who have any role attached to the object. ct_obj = ContentType.objects.get_for_model(obj) query = query.filter(content_type=ct_obj.id, object_id=obj.id) # Check if object belongs # to the role class. check_my_model(role, obj) # Looking for a role class using unique=True selected = list() for ur_obj in query: role = get_roleclass(ur_obj.role_class) if role.unique is True: selected.append(ur_obj.user) users_set = set(selected) if len(users_set) > 1: raise NotAllowed('Multiple unique roles was found using ' 'the function get_user. Use get_users ' 'instead.') if len(users_set) == 1: return selected[0] return None
def get_roles(user, obj=None): """ Return a list of role classes that is attached to "user". If "obj" is provided, the object must be attached as well. """ query = UserRole.objects.filter(user=user) if obj: ct_obj = ContentType.objects.get_for_model(obj) query = query.filter(content_type=ct_obj.id, object_id=obj.id) # Transform the string representations # into role classes and return as list. return [get_roleclass(ur_obj.role_class) for ur_obj in query]
def get_permissions_from_roles(roles, clean=False): """ roles: list or QuerySet of UserRole objects For given role(s), return a list of all allowed permissions. If clean=True, return the permissions without the Django app prefix. """ role_classes = [get_roleclass(ur.role_class) for ur in roles] permissions_lists = [r.allow for r in role_classes] # Flatten permissions list all_permissions = list( set([item for sublist in permissions_lists for item in sublist])) if clean: # Remove the app prefix from all permissions all_permissions_clean = [s.split('.')[1] for s in all_permissions] return (all_permissions_clean) else: return (all_permissions)
def role(self): return get_roleclass(self.role_class)