Пример #1
0
    def test_has_permissions_one_of_empty_permission(self):
        """
            Test the has_permissions_one_of() method with the empty permission.

            Expected result: `False`.
        """

        role = Role('Administrator')
        db.session.add(role)
        db.session.commit()

        self.assertEqual(0, role._permissions)
        self.assertTrue(role.has_permissions_one_of(Permission(0)))

        role.permissions = Permission.EditRole
        self.assertTrue(role.has_permissions_one_of(Permission(0)))
Пример #2
0
    def test_selected_permissions_get(self):
        """
            Test getting the set permissions from the form.

            Expected result: The `permissions` property returns all permissions that are selected in the form.
        """
        class PermissionTestForm(BasePermissionForm):
            """
                A simple form to which permission fields will be added.
            """

            pass

        # The preselected permissions.
        form = create_permission_form(PermissionTestForm, self.permissions)
        self.assertEqual(self.permissions, form.permissions)

        # Changed permissions with some selected.
        form = create_permission_form(PermissionTestForm, self.permissions)
        form.edituser.data = True
        form.editglobalsettings.data = False
        self.assertEqual(Permission.EditRole | Permission.EditUser,
                         form.permissions)

        # No selection of permissions.
        form = create_permission_form(PermissionTestForm, self.permissions)
        form.editglobalsettings.data = False
        form.editrole.data = False
        self.assertEqual(Permission(0), form.permissions)
Пример #3
0
    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)
Пример #4
0
    def test_selected_permissions_get_no_fields(self):
        """
            Test getting the tested permissions if no permission fields exist.

            Expected result: The empty permission is returned without any errors.
        """

        form = BasePermissionForm()
        self.assertEqual(Permission(0), form.permissions)
Пример #5
0
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
Пример #6
0
    def test_permissions_get_none(self):
        """
            Test getting the permission enum member if there are no permissions.

            Expected result: The empty permission.
        """

        role = Role('Administrator')

        self.assertIsNone(role._permissions)
        self.assertEqual(Permission(0), role.permissions)
Пример #7
0
    def test_permissions_get_less_than_zero(self):
        """
            Test getting the permission enum member if the permission integer is < 0.

            Expected result: The empty permission.
        """

        role = Role('Administrator')
        role._permissions = -1

        self.assertEqual(Permission(0), role.permissions)
Пример #8
0
    def permissions(self) -> Permission:
        """
            The (combination of) permissions that represent the permissions this role has.

            Assigning permissions will overwrite all existing permissions.

            If this role is the only one allowed to edit roles, but the new permissions do not include the permission to
            edit roles, this permission will automatically be added to the role to prevent cases where there is no role
            that can edit roles.

            :return: An enum member of :class:`app.userprofile.Permission` representing the role's permissions.
        """

        # For some reason, PyCharm thinks, self._permissions has type Permission...
        # noinspection PyTypeChecker
        if self._permissions is None or self._permissions < 0:
            return Permission(0)

        # noinspection PyTypeChecker
        return Permission(self._permissions)
Пример #9
0
    def test_permissions_get_zero(self):
        """
            Test getting the permission enum member if the permission integer is 0.

            Expected result: The empty permission.
        """

        role = Role('Administrator')
        db.session.add(role)
        db.session.commit()

        self.assertEqual(0, role._permissions)
        self.assertEqual(Permission(0), role.permissions)
Пример #10
0
    def test_permissions_set_none(self):
        """
            Test setting permissions without giving a permission.

            Expected result: The empty permission is set.
        """

        role = Role('Administrator')
        role._permissions = Permission.EditRole.value
        self.assertEqual(Permission.EditRole, role.permissions)

        role.permissions = None
        self.assertEqual(Permission(0).value, role._permissions)
Пример #11
0
    def test_selected_permissions_get_faulty_field_dict(self):
        """
            Test getting the tested permissions if no permission fields exist, but the permission fields dict say
            otherwise..

            Expected result: The empty permission is returned without any errors.
        """

        form = BasePermissionForm()
        permission = Permission.EditGlobalSettings
        form.permission_fields = OrderedDict([(permission.name, permission)])

        self.assertEqual(Permission(0), form.permissions)
Пример #12
0
    def test_has_permissions_one_of_multiple_permissions(self):
        """
            Test the has_permissions_one_of() method if a role has the requested permission (and others).

            Expected result: `True` when requesting the set permissions.
        """

        role = Role('Administrator')

        role.permissions = Permission.EditRole | Permission.EditUser
        self.assertTrue(role.has_permissions_one_of(Permission.EditRole))
        self.assertTrue(role.has_permissions_one_of(Permission.EditUser))
        self.assertTrue(
            role.has_permissions_one_of(Permission.EditRole,
                                        Permission.EditUser, Permission(0)))
Пример #13
0
    def permissions(self) -> Permission:
        """
            Get the permissions (:class:`.app.userprofile.Permission`) given by the form's data.

            :return: The (combined) permissions given by the form's data.
        """

        permissions = Permission(0)
        for field_name, permission in self.permission_fields.items():
            field = getattr(self, field_name, None)
            if not field:
                continue

            if field.data:
                permissions |= permission

        return permissions
Пример #14
0
def role_new() -> ResponseType:
    """
        Show and process a form to create a new role.

        :return: The response for this view.
    """

    new_role_form = create_permission_form(RoleNewForm, Permission(0))
    if new_role_form.validate_on_submit():
        role = Role(name=new_role_form.name.data)
        role.permissions = new_role_form.permissions
        db.session.add(role)
        db.session.commit()

        flash(_('The new role has been created.'))
        return redirect(url_for('.roles_list'))

    return render_template('administration/role_new.html', new_role_form=new_role_form)
Пример #15
0
    def test_assert_permission_required_without_required_permissions(
            self) -> None:
        """
            Test the assertion `assert_permission_required` assuming that a URL requires a permission, while in fact, it
            does not.

            Expected result: An error is raised for any other permission than the assumed one.
        """

        self.app.add_url_rule('/example', 'example', self.example_route)

        with self.assertRaises(self.failureException) as exception_cm:
            self.assert_permission_required('/example', Permission.EditUser)

        expected_messages = self._get_messages_for_accessible_url({
            Permission(0),
            Permission.EditRole,
            Permission.EditGlobalSettings,
            Permission.EditRole | Permission.EditGlobalSettings,
        })
        self.assertIn(str(exception_cm.exception), expected_messages)
Пример #16
0
    def test_assert_no_permission_required_but_url_requires_a_permission(
            self) -> None:
        """
            Test the assertion `assert_no_permission_required` if the accessed URL requires a permission.

            Expected result: An error is raised for any permission other than the required one.
        """

        decorator = permission_required(Permission.EditUser)
        decorated_view = decorator(self.example_route)
        self.app.add_url_rule('/example', 'example', decorated_view)

        with self.assertRaises(self.failureException) as exception_cm:
            self.assert_no_permission_required('/example')

        # The assertion can fail for any of these permissions since the assertion uses sets.
        expected_messages = self._get_messages_for_inaccessible_url({
            Permission(0), Permission.EditRole, Permission.EditGlobalSettings,
            Permission.EditRole | Permission.EditGlobalSettings
        })

        self.assertIn(str(exception_cm.exception), expected_messages)
Пример #17
0
    def permissions(self, permission: Optional[Permission]) -> None:
        """
            Set the given permissions for this role.

            This will overwrite all existing permissions.

            If this role is the only one allowed to edit roles, but the new permissions do not include the permission to
            edit roles, this permission will automatically be added to the role to prevent cases where there is no role
            that can edit roles.

            :param permission: An enum member of :class:`app.userprofile.Permission` representing the role's new
                               permissions (may be a combination of multiple enum members).
        """

        if permission is None:
            permission = Permission(0)

        # If the permission to edit roles is not included in the new permissions, but this is the only role allowed to
        # edit roles, re-add the permission to avoid a situation where no one can edit roles anymore.
        if permission & Permission.EditRole != Permission.EditRole and self.is_only_role_allowed_to_edit_roles(
        ):
            permission |= Permission.EditRole

        self._permissions = permission.value
Пример #18
0
    def test_permission_required_one_of_no_permission(self):
        """
            Test the `permission_required_one_of` decorator if the user does not have any of the requested permissions.

            Expected result: The request is aborted with an error 403.
        """

        email = '*****@*****.**'
        name = 'Jane Doe'
        password = '******'
        user = User(email, name)
        user.set_password(password)
        user.role = Role('Administrator')

        db.session.add(user)
        db.session.commit()

        user.login(email, password)

        self.assertEqual(Permission(0), user.role.permissions)

        with self.assertRaises(Forbidden):
            permission_required_one_of(
                Permission.EditRole, Permission.EditUser)(self.view_function)()