From b9d705a3047a3e1ca65ca61d8573d62aac798949 Mon Sep 17 00:00:00 2001 From: Nejc Habjan Date: Fri, 19 Jan 2024 12:23:36 +0100 Subject: [PATCH 1/8] feat(job_token_scope): support job token access allowlist API --- docs/gl_objects/job_token_scope.rst | 20 ++++++++++++++++++++ gitlab/v4/objects/job_token_scope.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+) diff --git a/docs/gl_objects/job_token_scope.rst b/docs/gl_objects/job_token_scope.rst index 370ffa282..2de8c6f1a 100644 --- a/docs/gl_objects/job_token_scope.rst +++ b/docs/gl_objects/job_token_scope.rst @@ -49,3 +49,23 @@ Refresh the current state of job token scope:: scope.refresh() print(scope.inbound_enabled) # False + +Get a project's CI/CD job token inbound allowlist:: + + allowlist = scope.allowlist.list() + +Add a project to the project's inbound allowlist:: + + allowed_project = scope.allowlist.create({"target_project_id": 42}) + +Remove a project from the project's inbound allowlist:: + + allowed_project.delete() + # or directly using a project ID + scope.allowlist.delete(42) + +.. warning:: + + Similar to above, the ID attributes you receive from the create and list + APIs are not consistent. To safely retrieve the ID of the allowlisted project + regardless of how the object was created, always use its ``.get_id()`` method. diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index 828fe012c..dcd29f55f 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -2,12 +2,18 @@ from gitlab.base import RESTManager, RESTObject from gitlab.mixins import ( + CreateMixin, + DeleteMixin, GetWithoutIdMixin, + ListMixin, + ObjectDeleteMixin, RefreshMixin, SaveMixin, UpdateMethod, UpdateMixin, ) +from gitlab.types import RequiredOptional + __all__ = [ "ProjectJobTokenScope", @@ -18,6 +24,8 @@ class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject): _id_attr = None + allowlist: "AllowlistedProjectManager" + class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager): _path = "/projects/{project_id}/job_token_scope" @@ -27,3 +35,23 @@ class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager): def get(self, **kwargs: Any) -> ProjectJobTokenScope: return cast(ProjectJobTokenScope, super().get(**kwargs)) + + +class AllowlistedProject(ObjectDeleteMixin, RESTObject): + _id_attr = "target_project_id" # note: only true for create endpoint + + def get_id(self) -> int: + """Returns the id of the resource. This override deals with + the fact that either an `id` or a `target_project_id` attribute + is returned by the server depending on the endpoint called.""" + try: + return cast(int, getattr(self, self._id_attr)) + except AttributeError: + return cast(int, getattr(self, "id")) + + +class AllowlistedProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): + _path = "/projects/{project_id}/job_token_scope/allowlist" + _obj_cls = AllowlistedProject + _from_parent_attrs = {"project_id": "project_id"} + _create_attrs = RequiredOptional(required=("target_project_id",)) From 2fb53e44ad9752b7bc7252f4b7967713246b0f51 Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Tue, 13 Feb 2024 16:15:25 +0000 Subject: [PATCH 2/8] test: add api integration test for ci_cd_token allowlist Signed-off-by: Tim Knight --- gitlab/v4/objects/job_token_scope.py | 1 - .../api/test_project_job_token_scope.py | 43 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 tests/functional/api/test_project_job_token_scope.py diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index dcd29f55f..1a1c58bf6 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -14,7 +14,6 @@ ) from gitlab.types import RequiredOptional - __all__ = [ "ProjectJobTokenScope", "ProjectJobTokenScopeManager", diff --git a/tests/functional/api/test_project_job_token_scope.py b/tests/functional/api/test_project_job_token_scope.py new file mode 100644 index 000000000..11e42de9b --- /dev/null +++ b/tests/functional/api/test_project_job_token_scope.py @@ -0,0 +1,43 @@ +def test_add_project_to_job_token_scope_allowlist(gl, project): + project_to_add = gl.projects.create({"name": "Ci_Cd_token_add_proj"}) + + scope = project.job_token_scope.get() + resp = scope.allowlist.create({"target_project_id": project_to_add.id}) + + assert resp.source_project_id == project.id + assert resp.target_project_id == project_to_add.id + + project_to_add.delete() + + +def test_projects_job_token_scope_allowlist_contains_added_project_name(gl, project): + scope = project.job_token_scope.get() + assert len(scope.allowlist.list()) == 0 + + project_name = "Ci_Cd_token_named_proj" + project_to_add = gl.projects.create({"name": project_name}) + scope.allowlist.create({"target_project_id": project_to_add.id}) + + scope.refresh() + assert any(allowed.name == project_name for allowed in scope.allowlist.list()) + + project_to_add.delete() + + +def test_remove_project_by_id_from_projects_job_token_scope_allowlist(gl, project): + scope = project.job_token_scope.get() + assert len(scope.allowlist.list()) == 0 + + project_to_add = gl.projects.create({"name": "Ci_Cd_token_remove_proj"}) + + scope.allowlist.create({"target_project_id": project_to_add.id}) + + scope.refresh() + assert len(scope.allowlist.list()) != 0 + + scope.allowlist.remove(project_to_add.id) + + scope.refresh() + assert len(scope.allowlist.list()) == 0 + + project_to_add.delete() From 09aed71f0db962e99822d34753972e6d727a971b Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Wed, 14 Feb 2024 11:25:05 +0000 Subject: [PATCH 3/8] feat: add support for groups_allowlist in job_token_scope Signed-off-by: Tim Knight --- docs/gl_objects/job_token_scope.rst | 21 +++++ gitlab/v4/objects/job_token_scope.py | 21 +++++ .../api/test_project_job_token_scope.py | 85 +++++++++++++++++-- tests/unit/objects/test_job_token_scope.py | 85 +++++++++++++++++++ 4 files changed, 206 insertions(+), 6 deletions(-) diff --git a/docs/gl_objects/job_token_scope.rst b/docs/gl_objects/job_token_scope.rst index 2de8c6f1a..348fc461a 100644 --- a/docs/gl_objects/job_token_scope.rst +++ b/docs/gl_objects/job_token_scope.rst @@ -69,3 +69,24 @@ Remove a project from the project's inbound allowlist:: Similar to above, the ID attributes you receive from the create and list APIs are not consistent. To safely retrieve the ID of the allowlisted project regardless of how the object was created, always use its ``.get_id()`` method. + +Get a project's CI/CD job token inbound groups allowlist:: + + allowlist = scope.groups_allowlist.list() + +Add a project to the project's inbound groups allowlist:: + + allowed_project = scope.groups_allowlist.create({"target_project_id": 42}) + +Remove a project from the project's inbound agroups llowlist:: + + allowed_project.delete() + # or directly using a Group ID + scope.groups_allowlist.delete(42) + +.. warning:: + + Similar to above, the ID attributes you receive from the create and list + APIs are not consistent. To safely retrieve the ID of the allowlisted group + regardless of how the object was created, always use its ``.get_id()`` method. + diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index 1a1c58bf6..d68d60218 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -24,6 +24,7 @@ class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject): _id_attr = None allowlist: "AllowlistedProjectManager" + groups_allowlist: "AllowlistedGroupManager" class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager): @@ -54,3 +55,23 @@ class AllowlistedProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager _obj_cls = AllowlistedProject _from_parent_attrs = {"project_id": "project_id"} _create_attrs = RequiredOptional(required=("target_project_id",)) + + +class AllowlistedGroup(ObjectDeleteMixin, RESTObject): + _id_attr = "target_group_id" # note: only true for create endpoint + + def get_id(self) -> int: + """Returns the id of the resource. This override deals with + the fact that either an `id` or a `target_project_id` attribute + is returned by the server depending on the endpoint called.""" + try: + return cast(int, getattr(self, self._id_attr)) + except AttributeError: + return cast(int, getattr(self, "id")) + + +class AllowlistedGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): + _path = "/projects/{project_id}/job_token_scope/groups_allowlist" + _obj_cls = AllowlistedProject + _from_parent_attrs = {"project_id": "project_id"} + _create_attrs = RequiredOptional(required=("target_group_id",)) diff --git a/tests/functional/api/test_project_job_token_scope.py b/tests/functional/api/test_project_job_token_scope.py index 11e42de9b..0d0466182 100644 --- a/tests/functional/api/test_project_job_token_scope.py +++ b/tests/functional/api/test_project_job_token_scope.py @@ -1,3 +1,26 @@ +# https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html#allow-any-project-to-access-your-project +def test_enable_limit_access_to_this_project(gl, project): + scope = project.job_token_scope.get() + + scope.enabled = True + scope.save() + + scope.refresh() + + assert scope.inbound_enabled + + +def test_disable_limit_access_to_this_project(gl, project): + scope = project.job_token_scope.get() + + scope.enabled = False + scope.save() + + scope.refresh() + + assert not scope.inbound_enabled + + def test_add_project_to_job_token_scope_allowlist(gl, project): project_to_add = gl.projects.create({"name": "Ci_Cd_token_add_proj"}) @@ -12,8 +35,6 @@ def test_add_project_to_job_token_scope_allowlist(gl, project): def test_projects_job_token_scope_allowlist_contains_added_project_name(gl, project): scope = project.job_token_scope.get() - assert len(scope.allowlist.list()) == 0 - project_name = "Ci_Cd_token_named_proj" project_to_add = gl.projects.create({"name": project_name}) scope.allowlist.create({"target_project_id": project_to_add.id}) @@ -26,18 +47,70 @@ def test_projects_job_token_scope_allowlist_contains_added_project_name(gl, proj def test_remove_project_by_id_from_projects_job_token_scope_allowlist(gl, project): scope = project.job_token_scope.get() - assert len(scope.allowlist.list()) == 0 project_to_add = gl.projects.create({"name": "Ci_Cd_token_remove_proj"}) scope.allowlist.create({"target_project_id": project_to_add.id}) scope.refresh() - assert len(scope.allowlist.list()) != 0 - scope.allowlist.remove(project_to_add.id) + scope.allowlist.delete(project_to_add.id) scope.refresh() - assert len(scope.allowlist.list()) == 0 + assert not any( + allowed.id == project_to_add.id for allowed in scope.allowlist.list() + ) project_to_add.delete() + + +def test_add_group_to_job_token_scope_allowlist(gl, project): + group_to_add = gl.groups.create( + {"name": "add_group", "path": "allowlisted-add-test"} + ) + + scope = project.job_token_scope.get() + resp = scope.groups_allowlist.create({"target_group_id": group_to_add.id}) + + assert resp.source_project_id == project.id + assert resp.target_group_id == group_to_add.id + + group_to_add.delete() + + +def test_projects_job_token_scope_groups_allowlist_contains_added_group_name( + gl, project +): + scope = project.job_token_scope.get() + group_name = "list_group" + group_to_add = gl.groups.create( + {"name": group_name, "path": "allowlisted-add-and-list-test"} + ) + + scope.groups_allowlist.create({"target_group_id": group_to_add.id}) + + scope.refresh() + assert any(allowed.name == group_name for allowed in scope.groups_allowlist.list()) + + group_to_add.delete() + + +def test_remove_group_by_id_from_projects_job_token_scope_groups_allowlist(gl, project): + scope = project.job_token_scope.get() + + group_to_add = gl.groups.create( + {"name": "delete_group", "path": "allowlisted-delete-test"} + ) + + scope.groups_allowlist.create({"target_group_id": group_to_add.id}) + + scope.refresh() + + scope.groups_allowlist.delete(group_to_add.id) + + scope.refresh() + assert not any( + allowed.name == group_to_add.name for allowed in scope.groups_allowlist.list() + ) + + group_to_add.delete() diff --git a/tests/unit/objects/test_job_token_scope.py b/tests/unit/objects/test_job_token_scope.py index 8348c79ff..407fae2e6 100644 --- a/tests/unit/objects/test_job_token_scope.py +++ b/tests/unit/objects/test_job_token_scope.py @@ -6,12 +6,55 @@ import responses from gitlab.v4.objects import ProjectJobTokenScope +from gitlab.v4.objects.job_token_scope import ( + AllowlistedGroupManager, + AllowlistedProjectManager, +) job_token_scope_content = { "inbound_enabled": True, "outbound_enabled": False, } +project_allowlist_content = [ + { + "id": 4, + "description": "", + "name": "Diaspora Client", + "name_with_namespace": "Diaspora / Diaspora Client", + "path": "diaspora-client", + "path_with_namespace": "diaspora/diaspora-client", + "created_at": "2013-09-30T13:46:02Z", + "default_branch": "main", + "tag_list": ["example", "disapora client"], + "topics": ["example", "disapora client"], + "ssh_url_to_repo": "git@gitlab.example.com:diaspora/diaspora-client.git", + "http_url_to_repo": "https://gitlab.example.com/diaspora/diaspora-client.git", + "web_url": "https://gitlab.example.com/diaspora/diaspora-client", + "avatar_url": "https://gitlab.example.com/uploads/project/avatar/4/uploads/avatar.png", + "star_count": 0, + "last_activity_at": "2013-09-30T13:46:02Z", + "namespace": { + "id": 2, + "name": "Diaspora", + "path": "diaspora", + "kind": "group", + "full_path": "diaspora", + "parent_id": "", + "avatar_url": "", + "web_url": "https://gitlab.example.com/diaspora", + }, + } +] + +groups_allowlist_content = [ + { + "id": 4, + "web_url": "https://gitlab.example.com/groups/diaspora/diaspora-group", + "name": "namegroup", + } +] + @pytest.fixture def resp_get_job_token_scope(): @@ -26,6 +69,32 @@ def resp_get_job_token_scope(): yield rsps +@pytest.fixture +def resp_get_allowlist(): + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/job_token_scope/allowlist", + json=project_allowlist_content, + content_type="application/json", + status=200, + ) + yield rsps + + +@pytest.fixture +def resp_get_groups_allowlist(): + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.GET, + url="http://localhost/api/v4/projects/1/job_token_scope/groups_allowlist", + json=groups_allowlist_content, + content_type="application/json", + status=200, + ) + yield rsps + + @pytest.fixture def resp_patch_job_token_scope(): with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: @@ -61,3 +130,19 @@ def test_save_job_token_scope(job_token_scope, resp_patch_job_token_scope): def test_update_job_token_scope(project, resp_patch_job_token_scope): project.job_token_scope.update(new_data={"enabled": False}) + + +def test_get_projects_allowlist(job_token_scope, resp_get_allowlist): + allowlist = job_token_scope.allowlist + assert isinstance(allowlist, AllowlistedProjectManager) + + allowlist_content = allowlist.list() + assert isinstance(allowlist_content, list) + + +def test_get_groups_allowlist(job_token_scope, resp_get_groups_allowlist): + allowlist = job_token_scope.groups_allowlist + assert isinstance(allowlist, AllowlistedGroupManager) + + allowlist_content = allowlist.list() + assert isinstance(allowlist_content, list) From 3cc75e277b4740351c3fbd0a509af9d8692117aa Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Wed, 14 Feb 2024 11:25:05 +0000 Subject: [PATCH 4/8] feat: add support for groups_allowlist in job_token_scope Signed-off-by: Tim Knight --- gitlab/v4/objects/job_token_scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index d68d60218..81d58a7ef 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -72,6 +72,6 @@ def get_id(self) -> int: class AllowlistedGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): _path = "/projects/{project_id}/job_token_scope/groups_allowlist" - _obj_cls = AllowlistedProject + _obj_cls = AllowlistedGroup _from_parent_attrs = {"project_id": "project_id"} _create_attrs = RequiredOptional(required=("target_group_id",)) From 3bfc72676808ce514dd0d78de0bcf111c8e5d649 Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Wed, 1 May 2024 11:50:48 +0100 Subject: [PATCH 5/8] test: add unit tests for job_token_scope Signed-off-by: Tim Knight --- gitlab/v4/objects/job_token_scope.py | 2 +- tests/unit/objects/test_job_token_scope.py | 52 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 1 deletion(-) diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index 81d58a7ef..7863fd159 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -62,7 +62,7 @@ class AllowlistedGroup(ObjectDeleteMixin, RESTObject): def get_id(self) -> int: """Returns the id of the resource. This override deals with - the fact that either an `id` or a `target_project_id` attribute + the fact that either an `id` or a `target_group_id` attribute is returned by the server depending on the endpoint called.""" try: return cast(int, getattr(self, self._id_attr)) diff --git a/tests/unit/objects/test_job_token_scope.py b/tests/unit/objects/test_job_token_scope.py index 407fae2e6..79aa88ceb 100644 --- a/tests/unit/objects/test_job_token_scope.py +++ b/tests/unit/objects/test_job_token_scope.py @@ -47,6 +47,11 @@ } ] +project_allowlist_created_content = { + "target_project_id": 2, + "project_id": 1, +} + groups_allowlist_content = [ { "id": 4, @@ -55,6 +60,11 @@ } ] +group_allowlist_created_content = { + "target_group_id": 4, + "project_id": 1, +} + @pytest.fixture def resp_get_job_token_scope(): @@ -82,6 +92,19 @@ def resp_get_allowlist(): yield rsps +@pytest.fixture +def resp_add_to_allowlist(): + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/job_token_scope/allowlist", + json=project_allowlist_created_content, + content_type="application/json", + status=200, + ) + yield rsps + + @pytest.fixture def resp_get_groups_allowlist(): with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: @@ -95,6 +118,19 @@ def resp_get_groups_allowlist(): yield rsps +@pytest.fixture +def resp_add_to_groups_allowlist(): + with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: + rsps.add( + method=responses.POST, + url="http://localhost/api/v4/projects/1/job_token_scope/groups_allowlist", + json=group_allowlist_created_content, + content_type="application/json", + status=200, + ) + yield rsps + + @pytest.fixture def resp_patch_job_token_scope(): with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: @@ -140,9 +176,25 @@ def test_get_projects_allowlist(job_token_scope, resp_get_allowlist): assert isinstance(allowlist_content, list) +def test_add_project_to_allowlist(job_token_scope, resp_add_to_allowlist): + allowlist = job_token_scope.allowlist + assert isinstance(allowlist, AllowlistedProjectManager) + + resp = allowlist.create({"target_project_id": 2}) + assert resp.get_id() == 2 + + def test_get_groups_allowlist(job_token_scope, resp_get_groups_allowlist): allowlist = job_token_scope.groups_allowlist assert isinstance(allowlist, AllowlistedGroupManager) allowlist_content = allowlist.list() assert isinstance(allowlist_content, list) + + +def test_add_group_to_allowlist(job_token_scope, resp_add_to_groups_allowlist): + allowlist = job_token_scope.groups_allowlist + assert isinstance(allowlist, AllowlistedGroupManager) + + resp = allowlist.create({"target_group_id": 4}) + assert resp.get_id() == 4 From b6e4d0121953fdc0e14be0aa34f502aa4f89125e Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Wed, 8 May 2024 09:46:35 +0100 Subject: [PATCH 6/8] chore: update job_token docs and object names Signed-off-by: Tim Knight --- docs/gl_objects/job_token_scope.rst | 11 ++++++++++- gitlab/v4/objects/job_token_scope.py | 20 ++++++++++---------- tests/unit/objects/test_job_token_scope.py | 12 ++++++------ 3 files changed, 26 insertions(+), 17 deletions(-) diff --git a/docs/gl_objects/job_token_scope.rst b/docs/gl_objects/job_token_scope.rst index 348fc461a..8bcbd1278 100644 --- a/docs/gl_objects/job_token_scope.rst +++ b/docs/gl_objects/job_token_scope.rst @@ -67,9 +67,18 @@ Remove a project from the project's inbound allowlist:: .. warning:: Similar to above, the ID attributes you receive from the create and list - APIs are not consistent. To safely retrieve the ID of the allowlisted project + APIs are not consistent (in create() the id is returned as ``source_project_id`` whereas list() returns as ``id``). To safely retrieve the ID of the allowlisted project regardless of how the object was created, always use its ``.get_id()`` method. +Using ``.get_id()``:: + + resp = allowlist.create({"target_project_id": 2}) + allowlist_id = resp.get_id() + + allowlists = project.allowlist.list() + for allowlist in allowlists: + allowlist_id == allowlist.get_id() + Get a project's CI/CD job token inbound groups allowlist:: allowlist = scope.groups_allowlist.list() diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index 7863fd159..f9b808ed9 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -23,8 +23,8 @@ class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject): _id_attr = None - allowlist: "AllowlistedProjectManager" - groups_allowlist: "AllowlistedGroupManager" + allowlist: "AllowlistProjectManager" + groups_allowlist: "AllowlistGroupManager" class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager): @@ -37,7 +37,7 @@ def get(self, **kwargs: Any) -> ProjectJobTokenScope: return cast(ProjectJobTokenScope, super().get(**kwargs)) -class AllowlistedProject(ObjectDeleteMixin, RESTObject): +class AllowlistProject(ObjectDeleteMixin, RESTObject): _id_attr = "target_project_id" # note: only true for create endpoint def get_id(self) -> int: @@ -47,17 +47,17 @@ def get_id(self) -> int: try: return cast(int, getattr(self, self._id_attr)) except AttributeError: - return cast(int, getattr(self, "id")) + return cast(int, self.id) -class AllowlistedProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): +class AllowlistProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): _path = "/projects/{project_id}/job_token_scope/allowlist" - _obj_cls = AllowlistedProject + _obj_cls = AllowlistProject _from_parent_attrs = {"project_id": "project_id"} _create_attrs = RequiredOptional(required=("target_project_id",)) -class AllowlistedGroup(ObjectDeleteMixin, RESTObject): +class AllowlistGroup(ObjectDeleteMixin, RESTObject): _id_attr = "target_group_id" # note: only true for create endpoint def get_id(self) -> int: @@ -67,11 +67,11 @@ def get_id(self) -> int: try: return cast(int, getattr(self, self._id_attr)) except AttributeError: - return cast(int, getattr(self, "id")) + return cast(int, self.id) -class AllowlistedGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): +class AllowlistGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): _path = "/projects/{project_id}/job_token_scope/groups_allowlist" - _obj_cls = AllowlistedGroup + _obj_cls = AllowlistGroup _from_parent_attrs = {"project_id": "project_id"} _create_attrs = RequiredOptional(required=("target_group_id",)) diff --git a/tests/unit/objects/test_job_token_scope.py b/tests/unit/objects/test_job_token_scope.py index 79aa88ceb..6669446c4 100644 --- a/tests/unit/objects/test_job_token_scope.py +++ b/tests/unit/objects/test_job_token_scope.py @@ -7,8 +7,8 @@ from gitlab.v4.objects import ProjectJobTokenScope from gitlab.v4.objects.job_token_scope import ( - AllowlistedGroupManager, - AllowlistedProjectManager, + AllowlistGroupManager, + AllowlistProjectManager, ) job_token_scope_content = { @@ -170,7 +170,7 @@ def test_update_job_token_scope(project, resp_patch_job_token_scope): def test_get_projects_allowlist(job_token_scope, resp_get_allowlist): allowlist = job_token_scope.allowlist - assert isinstance(allowlist, AllowlistedProjectManager) + assert isinstance(allowlist, AllowlistProjectManager) allowlist_content = allowlist.list() assert isinstance(allowlist_content, list) @@ -178,7 +178,7 @@ def test_get_projects_allowlist(job_token_scope, resp_get_allowlist): def test_add_project_to_allowlist(job_token_scope, resp_add_to_allowlist): allowlist = job_token_scope.allowlist - assert isinstance(allowlist, AllowlistedProjectManager) + assert isinstance(allowlist, AllowlistProjectManager) resp = allowlist.create({"target_project_id": 2}) assert resp.get_id() == 2 @@ -186,7 +186,7 @@ def test_add_project_to_allowlist(job_token_scope, resp_add_to_allowlist): def test_get_groups_allowlist(job_token_scope, resp_get_groups_allowlist): allowlist = job_token_scope.groups_allowlist - assert isinstance(allowlist, AllowlistedGroupManager) + assert isinstance(allowlist, AllowlistGroupManager) allowlist_content = allowlist.list() assert isinstance(allowlist_content, list) @@ -194,7 +194,7 @@ def test_get_groups_allowlist(job_token_scope, resp_get_groups_allowlist): def test_add_group_to_allowlist(job_token_scope, resp_add_to_groups_allowlist): allowlist = job_token_scope.groups_allowlist - assert isinstance(allowlist, AllowlistedGroupManager) + assert isinstance(allowlist, AllowlistGroupManager) resp = allowlist.create({"target_group_id": 4}) assert resp.get_id() == 4 From c6a1fc67ca5f125074bc437dc4d3f3a37baaa5ce Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Wed, 8 May 2024 10:54:10 +0100 Subject: [PATCH 7/8] refactor: use super().get_id() Signed-off-by: Tim Knight --- gitlab/v4/objects/job_token_scope.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index f9b808ed9..edf8b8236 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -44,10 +44,10 @@ def get_id(self) -> int: """Returns the id of the resource. This override deals with the fact that either an `id` or a `target_project_id` attribute is returned by the server depending on the endpoint called.""" - try: - return cast(int, getattr(self, self._id_attr)) - except AttributeError: - return cast(int, self.id) + project_id = cast(int, super().get_id()) + if project_id is not None: + return project_id + return cast(int, self.id) class AllowlistProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): @@ -64,10 +64,10 @@ def get_id(self) -> int: """Returns the id of the resource. This override deals with the fact that either an `id` or a `target_group_id` attribute is returned by the server depending on the endpoint called.""" - try: - return cast(int, getattr(self, self._id_attr)) - except AttributeError: - return cast(int, self.id) + group_id = cast(int, super().get_id()) + if group_id is not None: + return group_id + return cast(int, self.id) class AllowlistGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager): From 4aab77f50b329a77d96766ac78642d7882b8397a Mon Sep 17 00:00:00 2001 From: Tim Knight Date: Fri, 10 May 2024 10:04:59 +0100 Subject: [PATCH 8/8] test: cover .get_id() paths Signed-off-by: Tim Knight --- gitlab/v4/objects/job_token_scope.py | 12 ++++++------ tests/unit/objects/test_job_token_scope.py | 2 ++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py index edf8b8236..ed04a3146 100644 --- a/gitlab/v4/objects/job_token_scope.py +++ b/gitlab/v4/objects/job_token_scope.py @@ -44,9 +44,9 @@ def get_id(self) -> int: """Returns the id of the resource. This override deals with the fact that either an `id` or a `target_project_id` attribute is returned by the server depending on the endpoint called.""" - project_id = cast(int, super().get_id()) - if project_id is not None: - return project_id + target_project_id = cast(int, super().get_id()) + if target_project_id is not None: + return target_project_id return cast(int, self.id) @@ -64,9 +64,9 @@ def get_id(self) -> int: """Returns the id of the resource. This override deals with the fact that either an `id` or a `target_group_id` attribute is returned by the server depending on the endpoint called.""" - group_id = cast(int, super().get_id()) - if group_id is not None: - return group_id + target_group_id = cast(int, super().get_id()) + if target_group_id is not None: + return target_group_id return cast(int, self.id) diff --git a/tests/unit/objects/test_job_token_scope.py b/tests/unit/objects/test_job_token_scope.py index 6669446c4..473e5935e 100644 --- a/tests/unit/objects/test_job_token_scope.py +++ b/tests/unit/objects/test_job_token_scope.py @@ -174,6 +174,7 @@ def test_get_projects_allowlist(job_token_scope, resp_get_allowlist): allowlist_content = allowlist.list() assert isinstance(allowlist_content, list) + assert allowlist_content[0].get_id() == 4 def test_add_project_to_allowlist(job_token_scope, resp_add_to_allowlist): @@ -190,6 +191,7 @@ def test_get_groups_allowlist(job_token_scope, resp_get_groups_allowlist): allowlist_content = allowlist.list() assert isinstance(allowlist_content, list) + assert allowlist_content[0].get_id() == 4 def test_add_group_to_allowlist(job_token_scope, resp_add_to_groups_allowlist):