From fafd4dc8b11a023bc969465bacd347f0f7cb41f1 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Wed, 14 Dec 2022 15:34:56 +0100 Subject: [PATCH 01/10] Add templates permissions --- ansys/rep/client/jms/__init__.py | 2 +- ansys/rep/client/jms/api/jms_api.py | 20 ++++++ ansys/rep/client/jms/api/project_api.py | 10 +-- ansys/rep/client/jms/resource/__init__.py | 2 +- .../{project_permission.py => permission.py} | 10 +-- .../{project_permission.py => permission.py} | 10 +-- generate_resources.py | 8 +-- pyproject.toml | 2 +- tests/jms/test_project_permissions.py | 4 +- tests/jms/test_task_definition_templates.py | 65 ++++++++++++++++++- 10 files changed, 104 insertions(+), 29 deletions(-) rename ansys/rep/client/jms/resource/{project_permission.py => permission.py} (72%) rename ansys/rep/client/jms/schema/{project_permission.py => permission.py} (55%) diff --git a/ansys/rep/client/jms/__init__.py b/ansys/rep/client/jms/__init__.py index ad0ed904b..5e8289536 100644 --- a/ansys/rep/client/jms/__init__.py +++ b/ansys/rep/client/jms/__init__.py @@ -21,8 +21,8 @@ JobSelection, Licensing, ParameterMapping, + Permission, Project, - ProjectPermission, ResourceRequirements, Software, StringParameterDefinition, diff --git a/ansys/rep/client/jms/api/jms_api.py b/ansys/rep/client/jms/api/jms_api.py index da7e61fb2..d17307184 100644 --- a/ansys/rep/client/jms/api/jms_api.py +++ b/ansys/rep/client/jms/api/jms_api.py @@ -10,6 +10,7 @@ from ..resource import Operation from ..resource.evaluator import Evaluator +from ..resource.permission import Permission from ..resource.project import Project, ProjectSchema from ..resource.task_definition_template import TaskDefinitionTemplate from .base import create_objects, delete_objects, get_object, get_objects, update_objects @@ -153,6 +154,25 @@ def delete_task_definition_templates(self, templates: List[TaskDefinitionTemplat """ return delete_objects(self.client.session, self.url, templates) + # Task Definition Template Permissions + def get_task_definition_template_permissions( + self, template_id, as_objects=True + ) -> List[Permission]: + return get_objects( + self.client.session, + f"{self.url}/task_definition_templates/{template_id}", + Permission, + as_objects, + ) + + def update_task_definition_template_permissions( + self, template_id, permissions: List[Permission] + ): + # TODO: check if api returns something + return update_objects( + self.client.session, f"{self.url}/task_definition_templates/{template_id}", permissions + ) + ################################################################ # Operations def get_operations(self, as_objects=True, **query_params) -> List[Operation]: diff --git a/ansys/rep/client/jms/api/project_api.py b/ansys/rep/client/jms/api/project_api.py index d7ce45974..6036adfad 100644 --- a/ansys/rep/client/jms/api/project_api.py +++ b/ansys/rep/client/jms/api/project_api.py @@ -19,8 +19,8 @@ from ..resource.license_context import LicenseContext from ..resource.parameter_definition import ParameterDefinition from ..resource.parameter_mapping import ParameterMapping +from ..resource.permission import Permission, PermissionSchema from ..resource.project import Project -from ..resource.project_permission import ProjectPermission, ProjectPermissionSchema from ..resource.selection import JobSelection from ..resource.task import Task from ..resource.task_definition import TaskDefinition @@ -331,10 +331,10 @@ def delete_algorithms(self, algorithms: List[Algorithm]): ################################################################ # Permissions - def get_permissions(self, as_objects=True) -> List[ProjectPermission]: - return self._get_objects(ProjectPermission, as_objects=as_objects) + def get_permissions(self, as_objects=True) -> List[Permission]: + return self._get_objects(Permission, as_objects=as_objects, fields=None) - def update_permissions(self, permissions: List[ProjectPermission]): + def update_permissions(self, permissions: List[Permission]): # the rest api currently doesn't return anything on permissions update update_permissions(self.client, self.url, permissions) @@ -567,7 +567,7 @@ def update_permissions(client, project_api_url, permissions): url = f"{project_api_url}/permissions" - schema = ProjectPermissionSchema(many=True) + schema = PermissionSchema(many=True) serialized_data = schema.dump(permissions) json_data = json.dumps({"permissions": serialized_data}) r = client.session.put(f"{url}", data=json_data) diff --git a/ansys/rep/client/jms/resource/__init__.py b/ansys/rep/client/jms/resource/__init__.py index 4b93521e7..1175b62f9 100644 --- a/ansys/rep/client/jms/resource/__init__.py +++ b/ansys/rep/client/jms/resource/__init__.py @@ -18,7 +18,7 @@ IntParameterDefinition, StringParameterDefinition, BoolParameterDefinition from .parameter_mapping import ParameterMapping from .project import Project -from .project_permission import ProjectPermission +from .permission import Permission from .selection import JobSelection from .task import Task from .task_definition import Licensing, SuccessCriteria, Software, ResourceRequirements, TaskDefinition diff --git a/ansys/rep/client/jms/resource/project_permission.py b/ansys/rep/client/jms/resource/permission.py similarity index 72% rename from ansys/rep/client/jms/resource/project_permission.py rename to ansys/rep/client/jms/resource/permission.py index 77d2b53ff..c88b22cdb 100644 --- a/ansys/rep/client/jms/resource/project_permission.py +++ b/ansys/rep/client/jms/resource/permission.py @@ -1,10 +1,10 @@ # autogenerated code from marshmallow.utils import missing from ansys.rep.client.common import Object -from ..schema.project_permission import ProjectPermissionSchema +from ..schema.permission import PermissionSchema -class ProjectPermission(Object): - """ProjectPermission resource. +class Permission(Object): + """Permission resource. Parameters ---------- @@ -16,7 +16,7 @@ class ProjectPermission(Object): """ class Meta: - schema = ProjectPermissionSchema + schema = PermissionSchema rest_name = "permissions" def __init__(self, @@ -32,4 +32,4 @@ def __init__(self, self.obj_type = self.__class__.__name__ -ProjectPermissionSchema.Meta.object_class = ProjectPermission +PermissionSchema.Meta.object_class = Permission diff --git a/ansys/rep/client/jms/schema/project_permission.py b/ansys/rep/client/jms/schema/permission.py similarity index 55% rename from ansys/rep/client/jms/schema/project_permission.py rename to ansys/rep/client/jms/schema/permission.py index ce41317da..c4d12e5d8 100644 --- a/ansys/rep/client/jms/schema/project_permission.py +++ b/ansys/rep/client/jms/schema/permission.py @@ -1,17 +1,9 @@ -# ---------------------------------------------------------- -# Copyright (C) 2019 by -# ANSYS Switzerland GmbH -# www.ansys.com -# -# Author(s): F.Negri -# ---------------------------------------------------------- - from marshmallow import fields from ansys.rep.client.common import BaseSchema -class ProjectPermissionSchema(BaseSchema): +class PermissionSchema(BaseSchema): class Meta(BaseSchema.Meta): pass diff --git a/generate_resources.py b/generate_resources.py index 9476ccaa8..b3200a436 100644 --- a/generate_resources.py +++ b/generate_resources.py @@ -104,12 +104,12 @@ "resource_filename": "project", }, { - "schema": "ProjectPermissionSchema", - "schema_filename": "project_permission", + "schema": "PermissionSchema", + "schema_filename": "permission", "rest_name": "permissions", "additional_fields": [], - "class": "ProjectPermission", - "resource_filename": "project_permission", + "class": "Permission", + "resource_filename": "permission", }, { "schema": "ResourceRequirementsSchema", diff --git a/pyproject.toml b/pyproject.toml index 7ec74bb07..0c7887dfe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ show_missing = true [tool.pytest.ini_options] log_cli = true -log_cli_level = "INFO" +log_cli_level = "DEBUG" log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" log_cli_date_format = "%Y-%m-%d %H:%M:%S" markers = [ diff --git a/tests/jms/test_project_permissions.py b/tests/jms/test_project_permissions.py index a06061912..645d74515 100644 --- a/tests/jms/test_project_permissions.py +++ b/tests/jms/test_project_permissions.py @@ -14,7 +14,7 @@ from ansys.rep.client.auth import AuthApi, User from ansys.rep.client.exceptions import ClientError from ansys.rep.client.jms import JmsApi, ProjectApi -from ansys.rep.client.jms.resource import JobDefinition, Project, ProjectPermission +from ansys.rep.client.jms.resource import JobDefinition, Permission, Project from tests.rep_test import REPTestCase log = logging.getLogger(__name__) @@ -31,7 +31,7 @@ def grant_permissions(project_api: ProjectApi, user): permissions = project_api.get_permissions() log.info(f"Permissions before: {permissions}") permissions.append( - ProjectPermission( + Permission( permission_type="user", value_name=user.username, role="writer", value_id=user.id ) ) diff --git a/tests/jms/test_task_definition_templates.py b/tests/jms/test_task_definition_templates.py index a3abe95ca..e36245fa8 100644 --- a/tests/jms/test_task_definition_templates.py +++ b/tests/jms/test_task_definition_templates.py @@ -13,8 +13,10 @@ from marshmallow.utils import missing +from ansys.rep.client import Client +from ansys.rep.client.auth import AuthApi, User from ansys.rep.client.jms import JmsApi -from ansys.rep.client.jms.resource import TaskDefinitionTemplate +from ansys.rep.client.jms.resource import Permission, TaskDefinitionTemplate from ansys.rep.client.jms.schema.task_definition_template import TaskDefinitionTemplateSchema from tests.rep_test import REPTestCase @@ -143,6 +145,67 @@ def test_template_integration(self): templates = jms_api.get_task_definition_templates(name=template_name) self.assertEqual(len(templates), 0) + def test_template_permissions(self): + + client = self.client() + jms_api = JmsApi(client) + + templates = jms_api.get_task_definition_templates() + + # a regular deployment should have some default templates + # with read all permissions + some user defined ones with + # either user or group permissions + for template in templates: + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + for permission in permissions: + self.assertIn(permission.permission_type, ["user", "group", "anyone"]) + + # create new template and check default permissions + template = TaskDefinitionTemplate(name="my_template", version=uuid.uuid4()) + template = jms_api.create_task_definition_templates([template])[0] + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + self.assertEqual(len(permissions), 1) + self.assertEqual(permissions[0].permission_type, "user") + self.assertEqual(permissions[0].role, "admin") + self.assertIsNotNone(permissions[0].value_id) + + # create test user + auth_api = AuthApi(client) + user_credentials = { + "user1": {"username": f"testuser-{uuid.uuid4().hex[:8]}", "password": "test"} + } + user1 = auth_api.create_user( + User( + username=user_credentials["user1"]["username"], + password=user_credentials["user1"]["password"], + is_admin=False, + ) + ) + log.info(f"User 1: {user1}") + client1 = Client( + rep_url=self.rep_url, + username=user1.username, + password=user_credentials["user1"]["password"], + ) + jms_api1 = JmsApi(client1) + + # verify test user can't access the template + client1_templates = jms_api1.get_task_definition_templates(id=template.id) + + # grant read all permissions + permissions.append(Permission(permission_type="anyone", role="reader", value_id="None")) + log.debug(permissions) + permissions = jms_api.update_task_definition_template_permissions(template.id, permissions) + self.assertEqual(len(permissions), 2) + + # verify test user can now access the template + client1_templates = jms_api1.get_task_definition_templates(id=template.id) + self.assertEqual(len(client1_templates), 1) + self.assertEqual(client1_templates.name, template.name) + + # Delete template + jms_api.delete_task_definition_templates([template]) + if __name__ == "__main__": unittest.main() From e195c33128bfd9df8b27c934bea3d79987d8f478 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Thu, 15 Dec 2022 12:37:12 +0100 Subject: [PATCH 02/10] Adjust test and add schema doc --- ansys/rep/client/jms/api/jms_api.py | 17 +++++++++++------ ansys/rep/client/jms/resource/permission.py | 5 ++++- ansys/rep/client/jms/schema/permission.py | 12 +++++++++--- tests/jms/test_task_definition_templates.py | 8 ++++---- 4 files changed, 28 insertions(+), 14 deletions(-) diff --git a/ansys/rep/client/jms/api/jms_api.py b/ansys/rep/client/jms/api/jms_api.py index d17307184..bc5e56ce1 100644 --- a/ansys/rep/client/jms/api/jms_api.py +++ b/ansys/rep/client/jms/api/jms_api.py @@ -10,7 +10,7 @@ from ..resource import Operation from ..resource.evaluator import Evaluator -from ..resource.permission import Permission +from ..resource.permission import Permission, PermissionSchema from ..resource.project import Project, ProjectSchema from ..resource.task_definition_template import TaskDefinitionTemplate from .base import create_objects, delete_objects, get_object, get_objects, update_objects @@ -167,11 +167,16 @@ def get_task_definition_template_permissions( def update_task_definition_template_permissions( self, template_id, permissions: List[Permission] - ): - # TODO: check if api returns something - return update_objects( - self.client.session, f"{self.url}/task_definition_templates/{template_id}", permissions - ) + ) -> None: + if not permissions: + return + + url = f"{self.url}/task_definition_templates/{template_id}/permissions" + schema = PermissionSchema(many=True) + serialized_data = schema.dump(permissions) + json_data = json.dumps({"permissions": serialized_data}) + r = self.client.session.put(f"{url}", data=json_data) + return ################################################################ # Operations diff --git a/ansys/rep/client/jms/resource/permission.py b/ansys/rep/client/jms/resource/permission.py index c88b22cdb..dfc331652 100644 --- a/ansys/rep/client/jms/resource/permission.py +++ b/ansys/rep/client/jms/resource/permission.py @@ -9,9 +9,12 @@ class Permission(Object): Parameters ---------- permission_type : str - value_id : str + Either 'user', 'group', or 'anyone'. + value_id : str, optional + Can be the ID of a user or group. value_name : str, optional role : str + Either 'admin', 'writer', or 'reader'. """ diff --git a/ansys/rep/client/jms/schema/permission.py b/ansys/rep/client/jms/schema/permission.py index c4d12e5d8..891f11bd6 100644 --- a/ansys/rep/client/jms/schema/permission.py +++ b/ansys/rep/client/jms/schema/permission.py @@ -7,7 +7,13 @@ class PermissionSchema(BaseSchema): class Meta(BaseSchema.Meta): pass - permission_type = fields.String(required=True) - value_id = fields.String(required=True) + permission_type = fields.String( + required=True, metadata={"description": "Either 'user', 'group', or 'anyone'."} + ) + value_id = fields.String( + allow_none=True, metadata={"description": "Can be the ID of a user or group."} + ) value_name = fields.String(allow_none=True) - role = fields.String(required=True) + role = fields.String( + required=True, metadata={"description": "Either 'admin', 'writer', or 'reader'."} + ) diff --git a/tests/jms/test_task_definition_templates.py b/tests/jms/test_task_definition_templates.py index e36245fa8..fee424491 100644 --- a/tests/jms/test_task_definition_templates.py +++ b/tests/jms/test_task_definition_templates.py @@ -193,15 +193,15 @@ def test_template_permissions(self): client1_templates = jms_api1.get_task_definition_templates(id=template.id) # grant read all permissions - permissions.append(Permission(permission_type="anyone", role="reader", value_id="None")) - log.debug(permissions) - permissions = jms_api.update_task_definition_template_permissions(template.id, permissions) + permissions.append(Permission(permission_type="anyone", role="reader", value_id=None)) + jms_api.update_task_definition_template_permissions(template.id, permissions) + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) self.assertEqual(len(permissions), 2) # verify test user can now access the template client1_templates = jms_api1.get_task_definition_templates(id=template.id) self.assertEqual(len(client1_templates), 1) - self.assertEqual(client1_templates.name, template.name) + self.assertEqual(client1_templates[0].name, template.name) # Delete template jms_api.delete_task_definition_templates([template]) From 34cf4c549841a8e19f49e244af4d520fecc61cc1 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Thu, 15 Dec 2022 17:30:48 +0100 Subject: [PATCH 03/10] Complete test --- tests/jms/test_task_definition_templates.py | 27 ++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/tests/jms/test_task_definition_templates.py b/tests/jms/test_task_definition_templates.py index fee424491..d9c6f04f2 100644 --- a/tests/jms/test_task_definition_templates.py +++ b/tests/jms/test_task_definition_templates.py @@ -13,7 +13,7 @@ from marshmallow.utils import missing -from ansys.rep.client import Client +from ansys.rep.client import Client, REPError from ansys.rep.client.auth import AuthApi, User from ansys.rep.client.jms import JmsApi from ansys.rep.client.jms.resource import Permission, TaskDefinitionTemplate @@ -191,6 +191,7 @@ def test_template_permissions(self): # verify test user can't access the template client1_templates = jms_api1.get_task_definition_templates(id=template.id) + self.assertEqual(len(client1_templates), 0) # grant read all permissions permissions.append(Permission(permission_type="anyone", role="reader", value_id=None)) @@ -203,9 +204,33 @@ def test_template_permissions(self): self.assertEqual(len(client1_templates), 1) self.assertEqual(client1_templates[0].name, template.name) + # verify test user can't edit the template + client1_templates[0].version = client1_templates[0].version + "-dev" + + except_obj = None + try: + client1_templates = jms_api1.update_task_definition_templates(client1_templates) + except REPError as e: + except_obj = e + self.assertEqual(except_obj.response.status_code, 403) + self.assertEqual(except_obj.description, "Access to this resource has been restricted") + + # grant write permissions to the user + permissions.append(Permission(permission_type="user", role="writer", value_id=user1.id)) + jms_api.update_task_definition_template_permissions(template.id, permissions) + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + self.assertEqual(len(permissions), 3) + + # verify test user can now edit the template + client1_templates[0].version = client1_templates[0].version + "-dev" + client1_templates = jms_api1.update_task_definition_templates(client1_templates) + # Delete template jms_api.delete_task_definition_templates([template]) + # Delete user + auth_api.delete_user(user1) + if __name__ == "__main__": unittest.main() From 9f52031461b716e365477caafad2a15a1d009be9 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Thu, 15 Dec 2022 18:13:24 +0100 Subject: [PATCH 04/10] More testing --- tests/jms/test_task_definition_templates.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/jms/test_task_definition_templates.py b/tests/jms/test_task_definition_templates.py index d9c6f04f2..8659f3a37 100644 --- a/tests/jms/test_task_definition_templates.py +++ b/tests/jms/test_task_definition_templates.py @@ -228,6 +228,25 @@ def test_template_permissions(self): # Delete template jms_api.delete_task_definition_templates([template]) + # Let user1 create a template + template = TaskDefinitionTemplate(name="my_template", version=uuid.uuid4()) + template = jms_api1.create_task_definition_templates([template])[0] + permissions = jms_api1.get_task_definition_template_permissions(template_id=template.id) + self.assertEqual(len(permissions), 1) + self.assertEqual(permissions[0].permission_type, "user") + self.assertEqual(permissions[0].role, "admin") + self.assertEqual(permissions[0].value_id, user1.id) + + # verify that an admin user can access the template + admin_templates = jms_api.get_task_definition_templates(id=template.id) + log.info(admin_templates) + self.assertEqual(len(admin_templates), 1) + self.assertEqual(admin_templates[0].name, template.name) + self.assertEqual(admin_templates[0].version, template.version) + + # Delete template + jms_api1.delete_task_definition_templates([template]) + # Delete user auth_api.delete_user(user1) From 0c299dc1899356a0e060e4510f49a2580e8a24d7 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Fri, 16 Dec 2022 09:17:34 +0100 Subject: [PATCH 05/10] More testing --- tests/jms/test_task_definition_templates.py | 79 +++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/tests/jms/test_task_definition_templates.py b/tests/jms/test_task_definition_templates.py index 8659f3a37..4c803702e 100644 --- a/tests/jms/test_task_definition_templates.py +++ b/tests/jms/test_task_definition_templates.py @@ -250,6 +250,85 @@ def test_template_permissions(self): # Delete user auth_api.delete_user(user1) + def test_template_anyone_permission(self): + + client = self.client() + jms_api = JmsApi(client) + + # create new template and check default permissions + template = TaskDefinitionTemplate(name="my_template", version=uuid.uuid4()) + template = jms_api.create_task_definition_templates([template])[0] + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + self.assertEqual(len(permissions), 1) + self.assertEqual(permissions[0].permission_type, "user") + self.assertEqual(permissions[0].role, "admin") + self.assertIsNotNone(permissions[0].value_id) + + # create test user + auth_api = AuthApi(client) + user_credentials = { + "user1": {"username": f"testuser-{uuid.uuid4().hex[:8]}", "password": "test"} + } + user1 = auth_api.create_user( + User( + username=user_credentials["user1"]["username"], + password=user_credentials["user1"]["password"], + is_admin=False, + ) + ) + log.info(f"User 1: {user1}") + client1 = Client( + rep_url=self.rep_url, + username=user1.username, + password=user_credentials["user1"]["password"], + ) + jms_api1 = JmsApi(client1) + + # verify test user can't access the template + client1_templates = jms_api1.get_task_definition_templates(id=template.id) + self.assertEqual(len(client1_templates), 0) + + # grant read all permissions + permissions.append(Permission(permission_type="anyone", role="reader", value_id=None)) + jms_api.update_task_definition_template_permissions(template.id, permissions) + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + self.assertEqual(len(permissions), 2) + + # verify test user can now access the template + client1_templates = jms_api1.get_task_definition_templates(id=template.id) + self.assertEqual(len(client1_templates), 1) + self.assertEqual(client1_templates[0].name, template.name) + + # verify test user can't edit the template + client1_templates[0].version = client1_templates[0].version + "-dev" + + except_obj = None + try: + client1_templates = jms_api1.update_task_definition_templates(client1_templates) + except REPError as e: + except_obj = e + self.assertEqual(except_obj.response.status_code, 403) + self.assertEqual(except_obj.description, "Access to this resource has been restricted") + + # grant write all permissions + anyone_permission = next(p for p in permissions if p.permission_type == "anyone") + anyone_permission.role = "writer" + jms_api.update_task_definition_template_permissions(template.id, permissions) + permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + self.assertEqual(len(permissions), 2) + for p in permissions: + if p.permission_type == "anyone": + self.assertEqual(p.role, "writer") + + # verify test user can now edit the template + client1_templates = jms_api1.update_task_definition_templates(client1_templates) + + # Delete template + jms_api.delete_task_definition_templates([template]) + + # Delete user + auth_api.delete_user(user1) + if __name__ == "__main__": unittest.main() From 5d4f527ed2a7a64dbe0ba610f3d719d621781ff6 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Fri, 16 Dec 2022 12:44:24 +0100 Subject: [PATCH 06/10] Update PUT permissions --- ansys/rep/client/jms/api/jms_api.py | 22 ++++++++++----------- ansys/rep/client/jms/api/project_api.py | 20 +++---------------- tests/jms/test_project_permissions.py | 6 ++---- tests/jms/test_task_definition_templates.py | 12 ++++------- 4 files changed, 20 insertions(+), 40 deletions(-) diff --git a/ansys/rep/client/jms/api/jms_api.py b/ansys/rep/client/jms/api/jms_api.py index bc5e56ce1..18d8e8b05 100644 --- a/ansys/rep/client/jms/api/jms_api.py +++ b/ansys/rep/client/jms/api/jms_api.py @@ -10,7 +10,7 @@ from ..resource import Operation from ..resource.evaluator import Evaluator -from ..resource.permission import Permission, PermissionSchema +from ..resource.permission import Permission from ..resource.project import Project, ProjectSchema from ..resource.task_definition_template import TaskDefinitionTemplate from .base import create_objects, delete_objects, get_object, get_objects, update_objects @@ -166,17 +166,17 @@ def get_task_definition_template_permissions( ) def update_task_definition_template_permissions( - self, template_id, permissions: List[Permission] + self, + template_id, + permissions: List[Permission], + as_objects=True, ) -> None: - if not permissions: - return - - url = f"{self.url}/task_definition_templates/{template_id}/permissions" - schema = PermissionSchema(many=True) - serialized_data = schema.dump(permissions) - json_data = json.dumps({"permissions": serialized_data}) - r = self.client.session.put(f"{url}", data=json_data) - return + return update_objects( + self.client.session, + f"{self.url}/task_definition_templates/{template_id}", + permissions, + as_objects, + ) ################################################################ # Operations diff --git a/ansys/rep/client/jms/api/project_api.py b/ansys/rep/client/jms/api/project_api.py index 6036adfad..287d986a9 100644 --- a/ansys/rep/client/jms/api/project_api.py +++ b/ansys/rep/client/jms/api/project_api.py @@ -19,7 +19,7 @@ from ..resource.license_context import LicenseContext from ..resource.parameter_definition import ParameterDefinition from ..resource.parameter_mapping import ParameterMapping -from ..resource.permission import Permission, PermissionSchema +from ..resource.permission import Permission from ..resource.project import Project from ..resource.selection import JobSelection from ..resource.task import Task @@ -334,9 +334,8 @@ def delete_algorithms(self, algorithms: List[Algorithm]): def get_permissions(self, as_objects=True) -> List[Permission]: return self._get_objects(Permission, as_objects=as_objects, fields=None) - def update_permissions(self, permissions: List[Permission]): - # the rest api currently doesn't return anything on permissions update - update_permissions(self.client, self.url, permissions) + def update_permissions(self, permissions: List[Permission], as_objects=True): + return self._update_objects(permissions, as_objects=as_objects) ################################################################ # License contexts @@ -560,19 +559,6 @@ def sync_jobs(project_api: ProjectApi, jobs: List[Job]): r = project_api.client.session.put(f"{url}", data=json_data) -def update_permissions(client, project_api_url, permissions): - - if not permissions: - return - - url = f"{project_api_url}/permissions" - - schema = PermissionSchema(many=True) - serialized_data = schema.dump(permissions) - json_data = json.dumps({"permissions": serialized_data}) - r = client.session.put(f"{url}", data=json_data) - - @cached(cache=TTLCache(1024, 60), key=lambda project: project.id) def get_fs_url(project: Project): if project.file_storages == missing: diff --git a/tests/jms/test_project_permissions.py b/tests/jms/test_project_permissions.py index 645d74515..1e83cd1dd 100644 --- a/tests/jms/test_project_permissions.py +++ b/tests/jms/test_project_permissions.py @@ -35,8 +35,7 @@ def grant_permissions(project_api: ProjectApi, user): permission_type="user", value_name=user.username, role="writer", value_id=user.id ) ) - project_api.update_permissions(permissions) - permissions = project_api.get_permissions() + permissions = project_api.update_permissions(permissions) log.info(f"Permissions after: {permissions}") @@ -45,8 +44,7 @@ def remove_permissions(project_api: ProjectApi, user): permissions = project_api.get_permissions() log.info(f"Permissions before: {permissions}") permissions = [p for p in permissions if p.value_name != user.username] - project_api.update_permissions(permissions) - permissions = project_api.get_permissions() + permissions = project_api.update_permissions(permissions) log.info(f"Permissions after: {permissions}") diff --git a/tests/jms/test_task_definition_templates.py b/tests/jms/test_task_definition_templates.py index 4c803702e..8bf8f83cd 100644 --- a/tests/jms/test_task_definition_templates.py +++ b/tests/jms/test_task_definition_templates.py @@ -195,8 +195,7 @@ def test_template_permissions(self): # grant read all permissions permissions.append(Permission(permission_type="anyone", role="reader", value_id=None)) - jms_api.update_task_definition_template_permissions(template.id, permissions) - permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + permissions = jms_api.update_task_definition_template_permissions(template.id, permissions) self.assertEqual(len(permissions), 2) # verify test user can now access the template @@ -217,8 +216,7 @@ def test_template_permissions(self): # grant write permissions to the user permissions.append(Permission(permission_type="user", role="writer", value_id=user1.id)) - jms_api.update_task_definition_template_permissions(template.id, permissions) - permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + permissions = jms_api.update_task_definition_template_permissions(template.id, permissions) self.assertEqual(len(permissions), 3) # verify test user can now edit the template @@ -290,8 +288,7 @@ def test_template_anyone_permission(self): # grant read all permissions permissions.append(Permission(permission_type="anyone", role="reader", value_id=None)) - jms_api.update_task_definition_template_permissions(template.id, permissions) - permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + permissions = jms_api.update_task_definition_template_permissions(template.id, permissions) self.assertEqual(len(permissions), 2) # verify test user can now access the template @@ -313,8 +310,7 @@ def test_template_anyone_permission(self): # grant write all permissions anyone_permission = next(p for p in permissions if p.permission_type == "anyone") anyone_permission.role = "writer" - jms_api.update_task_definition_template_permissions(template.id, permissions) - permissions = jms_api.get_task_definition_template_permissions(template_id=template.id) + permissions = jms_api.update_task_definition_template_permissions(template.id, permissions) self.assertEqual(len(permissions), 2) for p in permissions: if p.permission_type == "anyone": From fc839b5c3dc0d6d9e5107d3d70033448418e9a5c Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Fri, 16 Dec 2022 14:01:18 +0100 Subject: [PATCH 07/10] Clean imports --- ansys/rep/client/jms/api/jms_api.py | 13 +++++++----- ansys/rep/client/jms/api/project_api.py | 27 ++++++++++++++----------- 2 files changed, 23 insertions(+), 17 deletions(-) diff --git a/ansys/rep/client/jms/api/jms_api.py b/ansys/rep/client/jms/api/jms_api.py index 18d8e8b05..3e2a56306 100644 --- a/ansys/rep/client/jms/api/jms_api.py +++ b/ansys/rep/client/jms/api/jms_api.py @@ -7,12 +7,15 @@ from ansys.rep.client.client import Client from ansys.rep.client.exceptions import REPError +from ansys.rep.client.jms.resource import ( + Evaluator, + Operation, + Permission, + Project, + TaskDefinitionTemplate, +) +from ansys.rep.client.jms.schema.project import ProjectSchema -from ..resource import Operation -from ..resource.evaluator import Evaluator -from ..resource.permission import Permission -from ..resource.project import Project, ProjectSchema -from ..resource.task_definition_template import TaskDefinitionTemplate from .base import create_objects, delete_objects, get_object, get_objects, update_objects log = logging.getLogger(__name__) diff --git a/ansys/rep/client/jms/api/project_api.py b/ansys/rep/client/jms/api/project_api.py index 287d986a9..3b3d660e9 100644 --- a/ansys/rep/client/jms/api/project_api.py +++ b/ansys/rep/client/jms/api/project_api.py @@ -11,19 +11,22 @@ from ansys.rep.client.client import Client from ansys.rep.client.common import Object from ansys.rep.client.exceptions import ClientError, REPError +from ansys.rep.client.jms.resource import ( + Algorithm, + File, + Job, + JobDefinition, + JobSelection, + LicenseContext, + ParameterDefinition, + ParameterMapping, + Permission, + Project, + Task, + TaskDefinition, +) +from ansys.rep.client.jms.schema.job import JobSchema -from ..resource.algorithm import Algorithm -from ..resource.file import File -from ..resource.job import Job, JobSchema -from ..resource.job_definition import JobDefinition -from ..resource.license_context import LicenseContext -from ..resource.parameter_definition import ParameterDefinition -from ..resource.parameter_mapping import ParameterMapping -from ..resource.permission import Permission -from ..resource.project import Project -from ..resource.selection import JobSelection -from ..resource.task import Task -from ..resource.task_definition import TaskDefinition from .base import create_objects, delete_objects, get_objects, update_objects from .jms_api import JmsApi, _monitor_operation, get_project From 32f186106c8b7f39949558b97e7a079d2aea2087 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Wed, 21 Dec 2022 09:16:07 +0100 Subject: [PATCH 08/10] Fix doc --- prepare_documentation.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/prepare_documentation.py b/prepare_documentation.py index ff533cb2f..b0915ee4d 100644 --- a/prepare_documentation.py +++ b/prepare_documentation.py @@ -31,8 +31,8 @@ Licensing, Operation, ParameterMapping, + Permission, Project, - ProjectPermission, ResourceRequirements, Software, StringParameterDefinition, @@ -66,7 +66,7 @@ def generate_openapi_specs(): for resource in [ Project, - ProjectPermission, + Permission, LicenseContext, Job, Algorithm, From f06123faacc6242c3761d01454ccaff0a7050a88 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Wed, 21 Dec 2022 09:35:22 +0100 Subject: [PATCH 09/10] Add permissions to doc --- ansys/rep/client/jms/api/jms_api.py | 10 ++++++---- doc/source/api/jms.rst | 6 ++++++ doc/source/conf.py | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/ansys/rep/client/jms/api/jms_api.py b/ansys/rep/client/jms/api/jms_api.py index 3e2a56306..a1c6bdd21 100644 --- a/ansys/rep/client/jms/api/jms_api.py +++ b/ansys/rep/client/jms/api/jms_api.py @@ -159,8 +159,9 @@ def delete_task_definition_templates(self, templates: List[TaskDefinitionTemplat # Task Definition Template Permissions def get_task_definition_template_permissions( - self, template_id, as_objects=True + self, template_id: str, as_objects: bool = True ) -> List[Permission]: + """Get permissions of a task definition template""" return get_objects( self.client.session, f"{self.url}/task_definition_templates/{template_id}", @@ -170,10 +171,11 @@ def get_task_definition_template_permissions( def update_task_definition_template_permissions( self, - template_id, + template_id: str, permissions: List[Permission], - as_objects=True, - ) -> None: + as_objects: bool = True, + ) -> List[Permission]: + """Update permissions of a task definition template""" return update_objects( self.client.session, f"{self.url}/task_definition_templates/{template_id}", diff --git a/doc/source/api/jms.rst b/doc/source/api/jms.rst index 664a01a60..9f2c27ec1 100644 --- a/doc/source/api/jms.rst +++ b/doc/source/api/jms.rst @@ -144,4 +144,10 @@ Task Definition Template :members: .. autoclass:: ansys.rep.client.jms.TaskDefinitionTemplate + :members: + +Permissions +^^^^^^^^^^^ + +.. autoclass:: ansys.rep.client.jms.Permission :members: \ No newline at end of file diff --git a/doc/source/conf.py b/doc/source/conf.py index 529bb1ec9..c4cd4e836 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -33,7 +33,7 @@ "sphinx.ext.napoleon", "sphinx.ext.todo", "sphinx.ext.extlinks", - # "sphinx.ext.viewcode", # to show pytho source code + # "sphinx.ext.viewcode", # to show python source code "sphinxcontrib.httpdomain", "sphinxcontrib.globalsubs", "sphinx.ext.intersphinx", From 71046fd3df2bf4d1e181175dc3600067ca136003 Mon Sep 17 00:00:00 2001 From: Federico Negri Date: Wed, 21 Dec 2022 10:38:25 +0100 Subject: [PATCH 10/10] Show only info log level for tests --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 0c7887dfe..7ec74bb07 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,7 +20,7 @@ show_missing = true [tool.pytest.ini_options] log_cli = true -log_cli_level = "DEBUG" +log_cli_level = "INFO" log_cli_format = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s)" log_cli_date_format = "%Y-%m-%d %H:%M:%S" markers = [