def test_permission_convert_from_json(self):
        """
        Conversion by JSON definition.

        Validate various implicit conversion of permission JSON definition.
        """
        utils.warn_version(__meta__.__version__,
                           "permission set conversion",
                           "3.0",
                           skip=True)

        perm = PermissionSet({
            "name": Permission.WRITE,
            "access": Access.DENY,
            "scope": Scope.MATCH
        })
        utils.check_val_equal(perm.name, Permission.WRITE)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.MATCH)
        perm = PermissionSet({
            "name": Permission.WRITE.value,
            "access": Access.DENY.value,
            "scope": Scope.MATCH.value
        })
        utils.check_val_equal(perm.name, Permission.WRITE)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.MATCH)
    def test_permission_convert_from_acl(self):
        """
        Conversion from Pyramid ACL definition.

        Validate various implicit conversion of permission elements to explicit definition.
        """
        utils.warn_version(__meta__.__version__,
                           "permission set conversion",
                           "3.0",
                           skip=True)

        perm = PermissionSet((Allow, 1, "write-deny-match"))
        utils.check_val_equal(perm.name, Permission.WRITE)
        utils.check_val_equal(
            perm.access,
            Access.DENY,
            msg="Explicit permission name prioritized over ACL access")
        utils.check_val_equal(perm.scope, Scope.MATCH)
        utils.check_val_equal(perm.type,
                              PermissionType.DIRECT,
                              msg="Should infer direct from user ID.")
        perm = PermissionSet((Deny, "group:1", "read"))
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.RECURSIVE)
        utils.check_val_equal(
            perm.type,
            PermissionType.INHERITED,
            msg="Should infer inherited from group specifier.")
        utils.check_raises(
            lambda: PermissionSet((Allow, "group:1", ALL_PERMISSIONS)),
            TypeError,
            msg=
            "Don't allow any object that makes the permission name not explicitly defined."
        )
    def test_permission_convert_from_string(self):
        """
        Conversion by implicit/explicit name.

        Validate various implicit conversion of permission name string to explicit definition.
        """
        utils.warn_version(__meta__.__version__,
                           "permission set conversion",
                           "3.0",
                           skip=True)

        perm = PermissionSet("read")  # old implicit format
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.ALLOW)
        utils.check_val_equal(perm.scope, Scope.RECURSIVE)
        perm = PermissionSet("read-match")  # old format
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.ALLOW)
        utils.check_val_equal(perm.scope, Scope.MATCH)
        perm = PermissionSet("read-allow-match")  # new explicit format
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.ALLOW)
        utils.check_val_equal(perm.scope, Scope.MATCH)
        perm = PermissionSet("read-allow-recursive")
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.ALLOW)
        utils.check_val_equal(perm.scope, Scope.RECURSIVE)
        perm = PermissionSet("read-deny-match")
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.MATCH)
    def test_permission_convert_from_tuple(self):
        """
        Conversion from Ziggurat :class:`PermissionTuple` object.

        Validate various implicit conversion of permission elements to explicit definition.
        """
        utils.warn_version(__meta__.__version__,
                           "permission set conversion",
                           "3.0",
                           skip=True)

        perm = PermissionSet(
            PermissionTuple(
                "user-name",
                "write-deny-match",
                "user",  # important: perm-name & type
                "group_id",
                "resource_id",
                "owner",
                "allowed"))  # these doesn't matter
        utils.check_val_equal(perm.name, Permission.WRITE)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.MATCH)
        utils.check_val_equal(
            perm.type,
            PermissionType.DIRECT,
            msg="PermissionTuple should also help identify type")
        perm = PermissionSet(
            PermissionTuple(
                "user-name",
                "write-deny-match",
                "group",  # important: perm-name & type
                "group_id",
                "resource_id",
                "owner",
                "allowed"))  # these doesn't matter
        utils.check_val_equal(perm.name, Permission.WRITE)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.MATCH)
        utils.check_val_equal(
            perm.type,
            PermissionType.INHERITED,
            msg="PermissionTuple should also help identify type")
    def test_permission_convert_from_enum(self):
        """
        Conversion by enum values.

        Validate various implicit conversion of permission name string to explicit definition.
        """
        utils.warn_version(__meta__.__version__,
                           "permission set conversion",
                           "3.0",
                           skip=True)

        perm = PermissionSet(Permission.READ)
        utils.check_val_equal(perm.name, Permission.READ)
        utils.check_val_equal(perm.access, Access.ALLOW)
        utils.check_val_equal(perm.scope, Scope.RECURSIVE)
        perm = PermissionSet(Permission.WRITE, access="deny")
        utils.check_val_equal(perm.name, Permission.WRITE)
        utils.check_val_equal(perm.access, Access.DENY)
        utils.check_val_equal(perm.scope, Scope.RECURSIVE)
    def test_format_permissions_allowed(self):
        """
        Validate that formats are also respected, but with additional auto-expansion of all *modifier* combinations on
        permission names when requesting :attr:`PermissionType.ALLOWED` permissions.

        .. seealso::
            :meth:`test_format_permissions_applied`
        """
        utils.warn_version(__meta__.__version__,
                           "permission format validation",
                           "3.0",
                           skip=True)

        # add duplicates with extra modifiers only to test removal
        # provide in random order to validate proper sorting
        # use multiple permission implementation to validate they are still handled
        test_perms = [
            PermissionSet(Permission.READ, Access.DENY, Scope.RECURSIVE),
            PermissionSet(Permission.READ, Access.DENY, Scope.MATCH),
            PermissionSet(Permission.READ, Access.ALLOW, Scope.RECURSIVE),
            PermissionSet(Permission.READ, Access.ALLOW, Scope.MATCH),
            Permission.READ,
            "write-match",  # old implicit format
            Permission.WRITE,
        ]
        format_perms = format_permissions(test_perms, PermissionType.ALLOWED)
        expect_names = [
            Permission.READ.value + "-" + Scope.MATCH.value,
            str(PermissionSet(Permission.READ, Access.ALLOW, Scope.MATCH)),
            Permission.READ.value,
            str(PermissionSet(Permission.READ, Access.ALLOW, Scope.RECURSIVE)),
            # no implicit name for denied
            str(PermissionSet(Permission.READ, Access.DENY, Scope.MATCH)),
            str(PermissionSet(Permission.READ, Access.DENY, Scope.RECURSIVE)),
            Permission.WRITE.value + "-" + Scope.MATCH.value,
            str(PermissionSet(Permission.WRITE, Access.ALLOW, Scope.MATCH)),
            Permission.WRITE.value,
            str(PermissionSet(Permission.WRITE, Access.ALLOW,
                              Scope.RECURSIVE)),
            # no implicit name for denied
            str(PermissionSet(Permission.WRITE, Access.DENY, Scope.MATCH)),
            str(PermissionSet(Permission.WRITE, Access.DENY, Scope.RECURSIVE)),
        ]
        expect_perms = [
            PermissionSet(Permission.READ, Access.ALLOW, Scope.MATCH,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.READ, Access.ALLOW, Scope.RECURSIVE,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.READ, Access.DENY, Scope.MATCH,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.READ, Access.DENY, Scope.RECURSIVE,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.WRITE, Access.ALLOW, Scope.MATCH,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.WRITE, Access.ALLOW, Scope.RECURSIVE,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.WRITE, Access.DENY, Scope.MATCH,
                          PermissionType.ALLOWED).json(),
            PermissionSet(Permission.WRITE, Access.DENY, Scope.RECURSIVE,
                          PermissionType.ALLOWED).json(),
        ]
        utils.check_all_equal(format_perms["permission_names"],
                              expect_names,
                              any_order=False)
        utils.check_all_equal(format_perms["permissions"],
                              expect_perms,
                              any_order=False)
    def test_format_permissions_applied(self):
        """
        Validate that provided permission sets are formatted as intended, with both implicit and explicit variants, and
        with both name strings and detailed JSON objects.
        """
        utils.warn_version(__meta__.__version__,
                           "permission format validation",
                           "3.0",
                           skip=True)

        usr_perm = models.UserPermission()
        usr_perm.perm_name = Permission.GET_FEATURE.value
        grp_perm = models.GroupPermission()
        grp_perm.perm_name = "write-match"  # using string for backward compatibility
        dup_perm = Permission.READ.value  # only one should remain in result
        dup_usr_perm = models.UserPermission()
        dup_usr_perm.perm_name = dup_perm  # also only one remains although different type
        only_perm = Permission.GET_CAPABILITIES
        deny_match_perm = PermissionSet(Permission.GET_LEGEND_GRAPHIC,
                                        Access.DENY, Scope.MATCH)
        deny_str_perm = Permission.GET_MAP.value + "-" + Access.DENY.value
        deny_recur_perm = PermissionSet(Permission.GET_METADATA, Access.DENY,
                                        Scope.RECURSIVE)
        # purposely use a random order to test sorting simultaneously to duplicate removal
        any_perms = [
            deny_match_perm, dup_perm, only_perm, usr_perm, dup_usr_perm,
            grp_perm, deny_str_perm, deny_recur_perm, deny_recur_perm
        ]

        perm_type = PermissionType.DIRECT  # anything else than 'allowed' to only get 'applied' permissions
        format_perms = format_permissions(any_perms, perm_type)
        expect_names = [
            # both implicit/explicit variants added for backward compatibility and new format for each applicable case
            only_perm.value,
            str(PermissionSet(only_perm, Access.ALLOW, Scope.RECURSIVE)),
            usr_perm.perm_name,
            str(PermissionSet(usr_perm.perm_name)),
            # deny only have explicit representation
            str(deny_match_perm),
            str(PermissionSet(deny_str_perm, Access.DENY, Scope.RECURSIVE)),
            str(
                PermissionSet(deny_recur_perm.name, deny_recur_perm.access,
                              Scope.RECURSIVE)),
            dup_perm,  # only one, other not present
            str(PermissionSet(dup_perm, Access.ALLOW, Scope.RECURSIVE)),
            grp_perm.perm_name,
            str(PermissionSet(grp_perm.perm_name, Access.ALLOW, Scope.MATCH)),
        ]
        expect_perms = [
            PermissionSet(Permission.GET_CAPABILITIES, Access.ALLOW,
                          Scope.RECURSIVE, perm_type).json(),
            PermissionSet(Permission.GET_FEATURE, Access.ALLOW,
                          Scope.RECURSIVE, perm_type).json(),
            PermissionSet(Permission.GET_LEGEND_GRAPHIC, Access.DENY,
                          Scope.MATCH, perm_type).json(),
            PermissionSet(Permission.GET_MAP, Access.DENY, Scope.RECURSIVE,
                          perm_type).json(),
            PermissionSet(Permission.GET_METADATA, Access.DENY,
                          Scope.RECURSIVE, perm_type).json(),
            PermissionSet(Permission.READ, Access.ALLOW, Scope.RECURSIVE,
                          perm_type).json(),
            PermissionSet(Permission.WRITE, Access.ALLOW, Scope.MATCH,
                          perm_type).json(),
        ]
        utils.check_all_equal(format_perms["permission_names"],
                              expect_names,
                              any_order=False)
        utils.check_all_equal(format_perms["permissions"],
                              expect_perms,
                              any_order=False)
Beispiel #8
0
    def test_EditUser_ApplyPermissions(self):
        """
        Verifies that UI button operations are working for the following workflow:
            0. Goto Edit User page.
            1. Change ``service-type`` tab to display services of type :class:`ServiceAPI`.
            2. Set new permissions onto an existing resources and submit them with ``Apply`` button.
            3. Verify the permissions are selected and displayed on page reload.
            4. Remove and modify permission from existing resource and submit.
            5. Validate that changes are reflected.

        Note:
            Only implemented locally with form submission of ``TestApp``.
        """
        utils.warn_version(self,
                           "update permission modifiers with option select",
                           "3.0",
                           skip=True)

        # make sure any sub-resource are all deleted to avoid conflict, then recreate service to add sub-resource
        utils.TestSetup.delete_TestService(self)
        body = utils.TestSetup.create_TestService(self)
        info = utils.TestSetup.get_ResourceInfo(self, override_body=body)
        svc_id, svc_name = info["resource_id"], info["service_name"]
        res_name = "resource1"
        sub_name = "resource2"
        body = utils.TestSetup.create_TestResource(
            self, parent_resource_id=svc_id, override_resource_name=res_name)
        info = utils.TestSetup.get_ResourceInfo(self, override_body=body)
        res_id = info["resource_id"]
        body = utils.TestSetup.create_TestResource(
            self, parent_resource_id=res_id, override_resource_name=sub_name)
        info = utils.TestSetup.get_ResourceInfo(self, override_body=body)
        sub_id = info["resource_id"]
        utils.TestSetup.create_TestGroup(self)
        utils.TestSetup.create_TestUser(self)

        # utilities for later tests
        def to_ui_permission(permission):
            # type: (Union[Str, PermissionSet]) -> Str
            return permission.explicit_permission if isinstance(
                permission, PermissionSet) else ""

        def check_ui_resource_permissions(perm_form, resource_id, permissions):
            select_res_id = "permission_resource_{}".format(resource_id)
            select_options = perm_form.fields[
                select_res_id]  # contains multiple select, one per applicable permission
            utils.check_val_equal(
                len(select_options),
                2,
                msg="Always 2 select combobox expected (read and write).")
            select_values = [select.value for select in select_options]
            if not permissions:
                utils.check_all_equal(
                    ["", ""],
                    select_values,
                    msg="When no permission is selected, values are empty")
                return
            # value must match exactly the *explicit* permission representation
            for r_perm in permissions:
                utils.check_val_is_in(r_perm, select_values)

        def check_api_resource_permissions(resource_permissions):
            for _r_id, _r_perms in resource_permissions:
                urp_path = "/users/{}/resources/{}/permissions".format(
                    self.test_user_name, _r_id)
                urp_resp = utils.test_request(self, "GET", urp_path)
                urp_body = utils.check_response_basic_info(urp_resp)
                ur_perms = [
                    perm.json() for perm in _r_perms
                    if isinstance(perm, PermissionSet)
                ]
                for perm in ur_perms:
                    perm["type"] = PermissionType.DIRECT.value
                permissions = urp_body["permissions"]
                for perm in permissions:
                    perm.pop("reason",
                             None)  # >= 3.4, don't care for this test
                utils.check_all_equal(permissions, ur_perms, any_order=True)

        # 0. goto user edit page (default first service selected)
        path = "/ui/users/{}/default".format(self.test_user_name)
        resp = utils.test_request(self, "GET", path)
        # 1. change to 'api' service-type, validate created test resources are all displayed in resource tree
        resp = resp.click(self.test_service_type
                          )  # tabs are '<a href=...>{service-type}</a>'
        body = utils.check_ui_response_basic_info(resp)
        text = body.replace("\n", "").replace("  ",
                                              "")  # ignore HTML formatting
        tree_keys = re.findall(r"<div class=\"tree-key\">(.*?)</div>", text)
        for r_name in [svc_name, res_name, sub_name]:
            utils.check_val_is_in(
                r_name,
                tree_keys,
                msg="Resource '{}' expected to be listed in tree.".format(
                    r_name))

        # 2. apply new permissions
        # 2.1 validate all initial values of permissions are empty
        res_form_name = "resources_permissions"  # form that wraps the displayed resource tree
        res_form_submit = "edit_permissions"  # id of the Apply 'submit' input of the form
        res_perm_form = resp.forms[res_form_name]
        for r_id in [svc_id, res_id, sub_id]:
            check_ui_resource_permissions(res_perm_form, r_id, [])
        # 2.2 apply new
        # NOTE: because tree-view is created by reversed order of permissions, we must provide them as [WRITE, READ]
        svc_perm1 = PermissionSet(Permission.READ, Access.ALLOW,
                                  Scope.RECURSIVE)
        svc_perms = ["", svc_perm1]
        res_perm1 = PermissionSet(Permission.READ, Access.DENY,
                                  Scope.RECURSIVE)
        res_perm2 = PermissionSet(Permission.WRITE, Access.ALLOW,
                                  Scope.RECURSIVE)
        res_perms = [res_perm2, res_perm1]
        sub_perm1 = PermissionSet(Permission.READ, Access.ALLOW, Scope.MATCH)
        sub_perms = ["", sub_perm1]
        data = {
            # set value for following correspond to 'select' option that was chosen
            "permission_resource_{}".format(svc_id):
            [to_ui_permission(perm) for perm in svc_perms],
            "permission_resource_{}".format(res_id):
            [to_ui_permission(perm) for perm in res_perms],
            "permission_resource_{}".format(sub_id):
            [to_ui_permission(perm) for perm in sub_perms],
        }
        resp = utils.TestSetup.check_FormSubmit(self,
                                                previous_response=resp,
                                                form_match=res_perm_form,
                                                form_submit=res_form_submit,
                                                form_data=data)

        # 3. validate result
        # 3.1 validate displayed UI permissions
        res_perm_form = resp.forms[res_form_name]
        check_ui_resource_permissions(
            res_perm_form, svc_id,
            [to_ui_permission(perm) for perm in svc_perms])
        check_ui_resource_permissions(
            res_perm_form, res_id,
            [to_ui_permission(perm) for perm in res_perms])
        check_ui_resource_permissions(
            res_perm_form, sub_id,
            [to_ui_permission(perm) for perm in sub_perms])
        # 3.2 validate applied using API (to make sure that changes are not only reflected in UI)
        check_api_resource_permissions([(svc_id, svc_perms),
                                        (res_id, res_perms),
                                        (sub_id, sub_perms)])

        # 4. remove permission: this is equivalent to re-apply the ones we want to keep without the one to remove
        #    modify permission: this is detected by combo of (res-id, perm-name) with different (access, scope)
        svc_perms_mod = ["",
                         ""]  # remove the previous (READ, ALLOW, RECURSIVE)
        res_perm1_mod = PermissionSet(Permission.READ, Access.ALLOW,
                                      Scope.RECURSIVE)  # DENY -> ALLOW
        res_perms_mod = [res_perm2,
                         res_perm1_mod]  # second WRITE permission is unchanged
        sub_perms_mod = sub_perms  # all unchanged for this resource
        data = {
            "permission_resource_{}".format(svc_id):
            [to_ui_permission(perm) for perm in svc_perms_mod],
            "permission_resource_{}".format(res_id):
            [to_ui_permission(perm) for perm in res_perms_mod],
            "permission_resource_{}".format(sub_id):
            [to_ui_permission(perm) for perm in sub_perms_mod],
        }
        resp = utils.TestSetup.check_FormSubmit(self,
                                                previous_response=resp,
                                                form_match=res_perm_form,
                                                form_submit=res_form_submit,
                                                form_data=data)

        # 5. validate applied permissions modifications
        res_perm_form = resp.forms[res_form_name]
        check_ui_resource_permissions(
            res_perm_form, svc_id,
            [to_ui_permission(perm) for perm in svc_perms_mod])
        check_ui_resource_permissions(
            res_perm_form, res_id,
            [to_ui_permission(perm) for perm in res_perms_mod])
        check_ui_resource_permissions(
            res_perm_form, sub_id,
            [to_ui_permission(perm) for perm in sub_perms_mod])
        check_api_resource_permissions([(svc_id, svc_perms_mod),
                                        (res_id, res_perms_mod),
                                        (sub_id, sub_perms_mod)])