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)
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)])