def test__accepts_variable_args(self): self.assertThat( is_instance_or_subclass(self.foo, Baz, Foo, Bar), Equals(True) ) self.assertThat( is_instance_or_subclass(self.foo, Baz, Bar), Equals(False) )
def test_accepts_tuple_or_list(self): self.assertThat(is_instance_or_subclass(self.foo, (Baz, Foo, Bar)), Equals(True)) self.assertThat(is_instance_or_subclass(self.bar, (Baz, Foo)), Equals(False)) self.assertThat(is_instance_or_subclass(self.baz, [Bar, Foo]), Equals(True))
def test_accepts_non_flat_list(self): self.assertThat( is_instance_or_subclass(self.foo, (Baz, (Bar, (Foo, )))), Equals(True), ) self.assertThat( is_instance_or_subclass(self.bar, *[Baz, [Bar, [Foo]]]), Equals(True), )
def test_rejects_incorrect_type(self): self.assertThat(is_instance_or_subclass(self.foo, Bar), Equals(False)) self.assertThat(is_instance_or_subclass(self.bar, Baz), Equals(False)) self.assertThat(is_instance_or_subclass(self.baz, Foo), Equals(False))
def test_accept_subclass(self): self.assertThat(is_instance_or_subclass(self.baz, Bar), Equals(True))
def test_returns_false_if_object_is_not_relevant(self): self.assertThat(is_instance_or_subclass("Bar", Bar), Equals(False))
def test_accepts_correct_type(self): self.assertThat(is_instance_or_subclass(self.foo, Foo), Equals(True)) self.assertThat(is_instance_or_subclass(self.bar, Bar), Equals(True)) self.assertThat(is_instance_or_subclass(self.baz, Baz), Equals(True))
def has_perm(self, user, perm, obj=None): # Note that a check for a superuser will never reach this code # because Django will return True (as an optimization) for every # permission check performed on a superuser. if not user.is_active: # Deactivated users, and in particular the node-init user, # are prohibited from accessing maasserver services. return False if isinstance(obj, Node): if perm == NODE_PERMISSION.VIEW: # Any registered user can view a node regardless of its state. return True elif perm == NODE_PERMISSION.EDIT: return obj.owner == user elif perm == NODE_PERMISSION.ADMIN: # 'admin_node' permission is solely granted to superusers. return False else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif isinstance(obj, (BlockDevice, FilesystemGroup)): if isinstance(obj, BlockDevice): node = obj.node else: node = obj.get_node() if perm == NODE_PERMISSION.VIEW: # If the node is not ownered or the owner is the user then # they can view the information. return node.owner is None or node.owner == user elif perm == NODE_PERMISSION.EDIT: return node.owner == user elif perm == NODE_PERMISSION.ADMIN: # 'admin_node' permission is solely granted to superusers. return False else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif isinstance(obj, Interface): if perm == NODE_PERMISSION.VIEW: # Any registered user can view a interface regardless # of its state. return True elif perm in NODE_PERMISSION.EDIT: # A device can be editted by its owner a node must be admin. node = obj.get_node() if node is None or node.node_type == NODE_TYPE.MACHINE: return user.is_superuser else: return node.owner == user elif perm in NODE_PERMISSION.ADMIN: # Admin permission is solely granted to superusers. return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif is_instance_or_subclass(obj, UNRESTRICTED_READ_MODELS): # This model is classified under 'unrestricted read' for any # logged-in user; so everyone can view, but only an admin can # do anything else. if perm == NODE_PERMISSION.VIEW: return True elif perm in ADMIN_PERMISSIONS: # Admin permission is solely granted to superusers. return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif is_instance_or_subclass(obj, ADMIN_RESTRICTED_MODELS): # Only administrators are allowed to read/write these objects. if perm in ADMIN_PERMISSIONS: return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) else: raise NotImplementedError( 'Invalid permission check (invalid object type).')
def has_perm(self, user, perm, obj=None): if not user.is_active: # Deactivated users, and in particular the node-init user, # are prohibited from accessing maasserver services. return False from maasserver.rbac import rbac rbac_enabled = rbac.is_enabled() visible_pools, view_all_pools = [], [] deploy_pools, admin_pools = [], [] if rbac_enabled: visible_pools = rbac.get_resource_pool_ids( user.username, 'view') view_all_pools = rbac.get_resource_pool_ids( user.username, 'view-all') deploy_pools = rbac.get_resource_pool_ids( user.username, 'deploy-machines') admin_pools = rbac.get_resource_pool_ids( user.username, 'admin-machines') # Sanity check that a `ResourcePool` is being checked against # `ResourcePoolPermission`. if (obj is not None and isinstance(obj, ResourcePool) and not isinstance(perm, ResourcePoolPermission)): raise TypeError( 'obj type of ResourcePool must be checked ' 'against a `ResourcePoolPermission`.') # Handle node permissions without objects. if perm == NodePermission.admin and obj is None: # User wants to admin writes to all nodes (aka. create a node), # must be superuser for those permissions. return user.is_superuser elif perm == NodePermission.view and obj is None: # XXX 2018-11-20 blake_r: View permission without an obj is used # for device create as a standard user. Currently there is no # specific DevicePermission and no way for this code path to know # its for a device. So it is represented using this path. # # View is only used for the create action, modifying a created # device uses the appropriate `NodePermission.edit` scoped to the # device being editted. if rbac_enabled: # User must either be global admin or have access to deploy # or admin some machines. return ( user.is_superuser or (len(deploy_pools) > 0 or len(admin_pools) > 0)) return True # ResourcePool permissions are handled specifically. if isinstance(perm, ResourcePoolPermission): return self._perm_resource_pool( user, perm, rbac, visible_pools, obj) if isinstance(obj, (Node, BlockDevice, FilesystemGroup)): if isinstance(obj, BlockDevice): obj = obj.node elif isinstance(obj, FilesystemGroup): obj = obj.get_node() if perm == NodePermission.view: return self._can_view( rbac_enabled, user, obj, visible_pools, view_all_pools, deploy_pools, admin_pools) elif perm == NodePermission.edit: can_edit = self._can_edit( rbac_enabled, user, obj, deploy_pools, admin_pools) return not obj.locked and can_edit elif perm == NodePermission.lock: # only machines can be locked can_edit = self._can_edit( rbac_enabled, user, obj, deploy_pools, admin_pools) return obj.pool_id is not None and can_edit elif perm == NodePermission.admin: return not obj.locked and self._can_admin( rbac_enabled, user, obj, admin_pools) else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif isinstance(obj, Interface): node = obj.get_node() if node is None: # Doesn't matter the permission level if the interface doesn't # have a node, the user must be a global admin. return user.is_superuser if perm == NodePermission.view: return self._can_view( rbac_enabled, user, node, visible_pools, view_all_pools, deploy_pools, admin_pools) elif perm == NodePermission.edit: # Machine interface can only be modified by an administrator # of the machine. Even the owner of the machine cannot modify # the interfaces on that machine, unless they have # administrator rights. if node.node_type == NODE_TYPE.MACHINE: return self._can_admin( rbac_enabled, user, node, admin_pools) # Other node types must be editable by the user. return self._can_edit( rbac_enabled, user, node, deploy_pools, admin_pools) elif perm == NodePermission.admin: # Admin permission is solely granted to superusers. return self._can_admin( rbac_enabled, user, node, admin_pools) else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif is_instance_or_subclass(obj, UNRESTRICTED_READ_MODELS): # This model is classified under 'unrestricted read' for any # logged-in user; so everyone can view, but only an admin can # do anything else. if perm == NodePermission.view: return True elif perm in ADMIN_PERMISSIONS: # Admin permission is solely granted to superusers. return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif is_instance_or_subclass(obj, ADMIN_RESTRICTED_MODELS): # Only administrators are allowed to read/write these objects. if perm in ADMIN_PERMISSIONS: return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) else: raise NotImplementedError( 'Invalid permission check (invalid object type).')
def has_perm(self, user, perm, obj=None): if not user.is_active: # Deactivated users, and in particular the node-init user, # are prohibited from accessing maasserver services. return False from maasserver.rbac import rbac rbac_enabled = rbac.is_enabled() visible_pools, admin_pools = [], [] if rbac_enabled: visible_pools = rbac.get_resource_pools( user.username, 'view').values_list( 'id', flat=True) admin_pools = rbac.get_resource_pools( user.username, 'admin-machines').values_list( 'id', flat=True) if isinstance(obj, (Node, BlockDevice, FilesystemGroup)): if isinstance(obj, BlockDevice): obj = obj.node elif isinstance(obj, FilesystemGroup): obj = obj.get_node() if perm == NodePermission.view: return self._can_view( rbac_enabled, user, obj, visible_pools, admin_pools) elif perm == NodePermission.edit: can_edit = self._can_edit( rbac_enabled, user, obj, visible_pools, admin_pools) return not obj.locked and can_edit elif perm == NodePermission.lock: # only machines can be locked can_edit = self._can_edit( rbac_enabled, user, obj, visible_pools, admin_pools) return obj.pool_id is not None and can_edit elif perm == NodePermission.admin: return self._can_admin( rbac_enabled, user, obj, admin_pools) else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif isinstance(obj, Interface): node = obj.get_node() if node is None: # Doesn't matter the permission level if the interface doesn't # have a node, the user must be a global admin. return user.is_superuser if perm == NodePermission.view: return self._can_view( rbac_enabled, user, node, visible_pools, admin_pools) elif perm == NodePermission.edit: # Machine interface can only be modified by an administrator # of the machine. Even the owner of the machine cannot modify # the interfaces on that machine, unless they have # administrator rights. if node.node_type == NODE_TYPE.MACHINE: return self._can_admin( rbac_enabled, user, node, admin_pools) # Other node types must be editable by the user. return self._can_edit( rbac_enabled, user, node, visible_pools, admin_pools) elif perm == NodePermission.admin: # Admin permission is solely granted to superusers. return self._can_admin( rbac_enabled, user, node, admin_pools) else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif is_instance_or_subclass(obj, UNRESTRICTED_READ_MODELS): # This model is classified under 'unrestricted read' for any # logged-in user; so everyone can view, but only an admin can # do anything else. if perm == NodePermission.view: return True elif perm in ADMIN_PERMISSIONS: # Admin permission is solely granted to superusers. return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) elif is_instance_or_subclass(obj, ADMIN_RESTRICTED_MODELS): # Only administrators are allowed to read/write these objects. if perm in ADMIN_PERMISSIONS: return user.is_superuser else: raise NotImplementedError( 'Invalid permission check (invalid permission name: %s).' % perm) else: raise NotImplementedError( 'Invalid permission check (invalid object type).')