def _assert_permissions(self, url: str, allowed_permissions: Set[Permission], method: str) -> None: """ Assert that the given URL can be accessed with the allowed permissions, but not with any other permission. :param url: The URL to access. :param allowed_permissions: List of permissions that must be able to access the URL. :param method: The HTTP method to access the URL by. """ for allowed_permission in allowed_permissions: self._assert_permission_grants_access(url, allowed_permission, method) all_permissions = Permission.get_permissions( include_empty_permission=True, all_combinations=True) prohibited_permissions = { permission for permission in all_permissions if permission not in allowed_permissions } for prohibited_permission in prohibited_permissions: self._assert_permission_does_not_grant_access( url, prohibited_permission, method)
def assert_permission_required_all(self, url: str, *permissions: Permission, method: str = 'GET') -> None: """ Assert that accessing the URL via the given method requires all of the specified permissions and that accessing the URL with the permissions is actually possible. :param url: The URL to access. :param permissions: The permissions that must be required to access the URL. :param method: The HTTP method to access the URL by. Defaults to `'GET'`. """ all_permissions = Permission.get_permissions( include_empty_permission=True, all_combinations=True) # allowed_permission = Permission(0) for permission in permissions: allowed_permission |= permission allowed_permissions = { p for p in all_permissions if p.includes_permission(allowed_permission) } self._assert_permissions(url, allowed_permissions, method)
def create_permission_form(form_class: Type[BasePermissionForm], preset_permissions: Permission, *args: Any, disabled_permissions: Optional[Permission] = None, **kwargs: Any) -> BasePermissionForm: """ Create a form object of the given class with fields to select permissions. :param form_class: The *class* of the form of which the object will be created. :param preset_permissions: The permissions whose fields will be preselected. :param disabled_permissions: The permissions whose state cannot be changed. :param args: Further arguments that will be passed into the form constructor. :param kwargs: Further keyword arguments that will be passed into the form constructor. :return: An object of the given form class, extended with the fields for setting permissions. :raise ValueError: If `form_class` is not a subclass of :class:`BasePermissionForm`. """ class ExtendedPermissionForm(form_class): # type: ignore """ A subclass of the given permission form class to which the permission fields will be added and which will be instantiated and returned. """ pass # Ensure we have all required functionality. if not issubclass(form_class, BasePermissionForm): raise ValueError('The form does not inherit from BasePermissionForm') if not disabled_permissions: disabled_permissions = Permission(0) # Insert the permission fields. permissions = Permission.get_permissions() for permission in sorted(permissions, key=lambda p: p.title): # Preset the permission field if necessary. default = preset_permissions.includes_permission(permission) # Disable the field if necessary. disabled = disabled_permissions.includes_permission(permission) # Create the field. field_name = permission.name.lower() field = BooleanField(permission.title, description=permission.description, default=default, render_kw={'disabled': disabled}) # Add the field to the form and remember which permission it belongs to. setattr(ExtendedPermissionForm, field_name, field) ExtendedPermissionForm.permission_fields[field_name] = permission extended_form = ExtendedPermissionForm(*args, **kwargs) extended_form.order_fields() return extended_form
def assert_no_permission_required(self, url: str, method: str = 'GET') -> None: """ Assert that accessing the URL via the given method requires no permission at all and that accessing the URL with any permission is actually possible. The test checks for a response code of 403. This can lead to a false positive if a route aborts with an error 403. :param url: The URL to access. :param method: The HTTP method to access the URL by. Defaults to `'GET'`. """ allowed_permissions = Permission.get_permissions( include_empty_permission=True, all_combinations=True) self._assert_permissions(url, allowed_permissions, method)
def assert_permission_required_one_of(self, url: str, *permissions: Permission, method: str = 'GET') -> None: """ Assert that accessing the URL via the given method requires one of the specified permissions and that accessing the URL with the permission is actually possible, while accessing the URL with any other permission fails. :param url: The url to access. :param permissions: The permissions that must be required to access the URL. :param method: The HTTP method to access the URL by. Defaults to `'GET'`. """ all_permissions = Permission.get_permissions( include_empty_permission=True, all_combinations=True) allowed_permissions = set({}) for permission in permissions: allowed_permissions.update({ p for p in all_permissions if p.includes_permission(permission) }) self._assert_permissions(url, allowed_permissions, method)
def assert_permission_required(self, url: str, permission: Permission, method: str = 'GET') -> None: """ Assert that accessing the URL via the given method requires the specified permission and that accessing the URL with the permission is actually possible. The test checks for a response code of 403. This can lead to a false positive if a route does not require the specified permission but aborts with an error 403 in some other case. :param url: The URL to access. :param permission: The permission that must be required to access the URL. :param method: The HTTP method to access the URL by. Defaults to `'GET'`. """ all_permissions = Permission.get_permissions( include_empty_permission=True, all_combinations=True) allowed_permissions = { p for p in all_permissions if p.includes_permission(permission) } self._assert_permissions(url, allowed_permissions, method)