From 5860b4118211993278f96fd3df6130ccb727d377 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Jankowski?= Date: Wed, 16 Mar 2022 12:54:24 +0100 Subject: [PATCH] Added e2e tests and support for visibility workspace (#843) --- CHANGELOG.md | 1 + e2e_tests/management/test_management.py | 74 +++++++++++++++++++++++++ neptune/management/exceptions.py | 7 ++- neptune/management/internal/api.py | 8 ++- neptune/management/internal/dto.py | 2 + neptune/management/internal/types.py | 1 + 6 files changed, 90 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11f74b942..b043d7764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ## neptune-client 0.15.2 [UNRELEASED] ## Features +- Added support for workspace visibility in Management API ([#843](https://github.com/neptune-ai/neptune-client/pull/843)) - Exposed container with a property of Handler ([#864](https://github.com/neptune-ai/neptune-client/pull/864)) ## neptune-client 0.15.1 diff --git a/e2e_tests/management/test_management.py b/e2e_tests/management/test_management.py index 8d57696d5..b62e49441 100644 --- a/e2e_tests/management/test_management.py +++ b/e2e_tests/management/test_management.py @@ -24,6 +24,10 @@ delete_project, remove_project_member, ) +from neptune.management.exceptions import ( + UserAlreadyHasAccess, + UserNotExistsOrWithoutAccess, +) from neptune.management.internal.utils import normalize_project_name from e2e_tests.base import BaseE2ETest, fake from e2e_tests.utils import a_project_name, Environment @@ -103,3 +107,73 @@ def test_standard_scenario(self, environment: Environment): assert project_identifier not in get_project_list( api_token=environment.admin_token ) + + def test_visibility_workspace(self, environment: "Environment"): + project_name, project_key = a_project_name( + project_slug=f"{fake.slug()}-workspace" + ) + project_identifier = normalize_project_name( + name=project_name, workspace=environment.workspace + ) + + assert project_identifier not in get_project_list( + api_token=environment.admin_token + ) + assert environment.user in get_workspace_member_list( + name=environment.workspace, api_token=environment.admin_token + ) + assert ( + get_workspace_member_list( + name=environment.workspace, api_token=environment.admin_token + ).get(environment.user) + == "member" + ) + + created_project_identifier = create_project( + name=project_name, + key=project_key, + visibility="workspace", + workspace=environment.workspace, + api_token=environment.admin_token, + ) + + assert created_project_identifier == project_identifier + assert created_project_identifier in get_project_list( + api_token=environment.admin_token + ) + assert environment.user in get_project_member_list( + name=created_project_identifier, api_token=environment.admin_token + ) + assert ( + get_project_member_list( + name=created_project_identifier, api_token=environment.admin_token + ).get(environment.user) + == "owner" + ) + + with pytest.raises(UserAlreadyHasAccess): + add_project_member( + name=created_project_identifier, + username=environment.user, + role="contributor", + api_token=environment.admin_token, + ) + + assert created_project_identifier in get_project_list( + api_token=environment.user_token + ) + + with pytest.raises(UserNotExistsOrWithoutAccess): + remove_project_member( + name=created_project_identifier, + username=environment.user, + api_token=environment.admin_token, + ) + + delete_project( + name=created_project_identifier, api_token=environment.admin_token + ) + + assert project_identifier not in get_project_list( + api_token=environment.admin_token + ) diff --git a/neptune/management/exceptions.py b/neptune/management/exceptions.py index 706d8f665..abfadb69f 100644 --- a/neptune/management/exceptions.py +++ b/neptune/management/exceptions.py @@ -91,12 +91,15 @@ class AccessRevokedOnMemberRemoval(ManagementOperationFailure): class UserNotExistsOrWithoutAccess(ManagementOperationFailure): code = 9 - description = 'User "{user}" not exists or has no access to project "{project}".' + description = ( + 'User "{user}" does not exist or has no access to project "{project}". ' + "If the project visibility is set to workspace, a user cannot be added or removed." + ) class UserAlreadyHasAccess(ManagementOperationFailure): code = 10 - description = 'User "{user}" already has access to project "{project}".' + description = 'User "{user}" already has access to the project "{project}". Role already set to "{role}".' class ProjectsLimitReached(ManagementOperationFailure): diff --git a/neptune/management/internal/api.py b/neptune/management/internal/api.py index 4c211177f..82648b0e7 100644 --- a/neptune/management/internal/api.py +++ b/neptune/management/internal/api.py @@ -301,7 +301,13 @@ def add_project_member( except HTTPNotFound as e: raise ProjectNotFound(name=project_identifier) from e except HTTPConflict as e: - raise UserAlreadyHasAccess(user=username, project=project_identifier) from e + members = get_project_member_list( + name=name, workspace=workspace, api_token=api_token + ) + user_role = members.get(username) + raise UserAlreadyHasAccess( + user=username, project=project_identifier, role=user_role + ) from e @with_api_exceptions_handler diff --git a/neptune/management/internal/dto.py b/neptune/management/internal/dto.py index f9cc1aed3..24e4e8dbf 100644 --- a/neptune/management/internal/dto.py +++ b/neptune/management/internal/dto.py @@ -28,6 +28,7 @@ class ProjectVisibilityDTO(Enum): PRIVATE = "priv" PUBLIC = "pub" + WORKSPACE = "workspace" @classmethod def from_str(cls, visibility: str) -> "ProjectVisibilityDTO": @@ -37,6 +38,7 @@ def from_str(cls, visibility: str) -> "ProjectVisibilityDTO": return { ProjectVisibility.PRIVATE: ProjectVisibilityDTO.PRIVATE, ProjectVisibility.PUBLIC: ProjectVisibilityDTO.PUBLIC, + ProjectVisibility.WORKSPACE: ProjectVisibilityDTO.WORKSPACE, }[visibility] except KeyError as e: raise UnsupportedValue(enum=cls.__name__, value=visibility) from e diff --git a/neptune/management/internal/types.py b/neptune/management/internal/types.py index cc4a07f92..a32db2b8e 100644 --- a/neptune/management/internal/types.py +++ b/neptune/management/internal/types.py @@ -16,6 +16,7 @@ class ProjectVisibility: PRIVATE = "priv" PUBLIC = "pub" + WORKSPACE = "workspace" class ProjectMemberRole: