prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Support /projects/:id/job_token_scope/allowlist
  I would like to access the job token allow list through the Gitlab API. 
  
  Docs: 
  - [Get a project’s CI/CD job token inbound allowlist](https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-inbound-allowlist)
  - [Allow access to your project with a job token](https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html#allow-access-to-your-project-with-a-job-token)
  
  API endpoint: 
  ```
  GET/POST/DELETE /projects/:id/job_token_scope/allowlist
  ```
  
  I currently have the following manager to access the job token scope allow list:
  
  ```
  class ProjectJobTokenScopeAllowlistManager(
      gitlab.mixins.ListMixin,
      gitlab.mixins.CreateMixin,
      gitlab.mixins.DeleteMixin,
      gitlab.base.RESTManager,
  ):
      _path = "/projects/{project_id}/job_token_scope/allowlist"
      _obj_cls = gitlab.v4.objects.Project
      _from_parent_attrs = {"project_id": "id"}
      _create_attrs = gitlab.types.RequiredOptional(required=("target_project_id",))
  ```
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `gitlab/v4/objects/job_token_scope.py`
  Content:
  ```
  1 from typing import Any, cast
  2 
  3 from gitlab.base import RESTManager, RESTObject
  4 from gitlab.mixins import (
  5     GetWithoutIdMixin,
  6     RefreshMixin,
  7     SaveMixin,
  8     UpdateMethod,
  9     UpdateMixin,
  10 )
  11 
  12 __all__ = [
  13     "ProjectJobTokenScope",
  14     "ProjectJobTokenScopeManager",
  15 ]
  16 
  17 
  18 class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject):
  19     _id_attr = None
  20 
  21 
  22 class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
  23     _path = "/projects/{project_id}/job_token_scope"
  24     _obj_cls = ProjectJobTokenScope
  25     _from_parent_attrs = {"project_id": "id"}
  26     _update_method = UpdateMethod.PATCH
  27 
  28     def get(self, **kwargs: Any) -> ProjectJobTokenScope:
  29         return cast(ProjectJobTokenScope, super().get(**kwargs))
  30
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py
  --- a/gitlab/v4/objects/job_token_scope.py
  +++ b/gitlab/v4/objects/job_token_scope.py
  @@ -2,12 +2,17 @@
   
   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 +23,9 @@
   class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject):
       _id_attr = None
   
  +    allowlist: "AllowlistProjectManager"
  +    groups_allowlist: "AllowlistGroupManager"
  +
   
   class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):
       _path = "/projects/{project_id}/job_token_scope"
  @@ -27,3 +35,43 @@
   
       def get(self, **kwargs: Any) -> ProjectJobTokenScope:
           return cast(ProjectJobTokenScope, super().get(**kwargs))
  +
  +
  +class AllowlistProject(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."""
  +        target_project_id = cast(int, super().get_id())
  +        if target_project_id is not None:
  +            return target_project_id
  +        return cast(int, self.id)
  +
  +
  +class AllowlistProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
  +    _path = "/projects/{project_id}/job_token_scope/allowlist"
  +    _obj_cls = AllowlistProject
  +    _from_parent_attrs = {"project_id": "project_id"}
  +    _create_attrs = RequiredOptional(required=("target_project_id",))
  +
  +
  +class AllowlistGroup(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_group_id` attribute
  +        is returned by the server depending on the endpoint called."""
  +        target_group_id = cast(int, super().get_id())
  +        if target_group_id is not None:
  +            return target_group_id
  +        return cast(int, self.id)
  +
  +
  +class AllowlistGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):
  +    _path = "/projects/{project_id}/job_token_scope/groups_allowlist"
  +    _obj_cls = AllowlistGroup
  +    _from_parent_attrs = {"project_id": "project_id"}
  +    _create_attrs = RequiredOptional(required=("target_group_id",))
  
verification_info: {"golden_diff": "diff --git a/gitlab/v4/objects/job_token_scope.py b/gitlab/v4/objects/job_token_scope.py\n--- a/gitlab/v4/objects/job_token_scope.py\n+++ b/gitlab/v4/objects/job_token_scope.py\n@@ -2,12 +2,17 @@\n \n from gitlab.base import RESTManager, RESTObject\n from gitlab.mixins import (\n+    CreateMixin,\n+    DeleteMixin,\n     GetWithoutIdMixin,\n+    ListMixin,\n+    ObjectDeleteMixin,\n     RefreshMixin,\n     SaveMixin,\n     UpdateMethod,\n     UpdateMixin,\n )\n+from gitlab.types import RequiredOptional\n \n __all__ = [\n     \"ProjectJobTokenScope\",\n@@ -18,6 +23,9 @@\n class ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject):\n     _id_attr = None\n \n+    allowlist: \"AllowlistProjectManager\"\n+    groups_allowlist: \"AllowlistGroupManager\"\n+\n \n class ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):\n     _path = \"/projects/{project_id}/job_token_scope\"\n@@ -27,3 +35,43 @@\n \n     def get(self, **kwargs: Any) -> ProjectJobTokenScope:\n         return cast(ProjectJobTokenScope, super().get(**kwargs))\n+\n+\n+class AllowlistProject(ObjectDeleteMixin, RESTObject):\n+    _id_attr = \"target_project_id\"  # note: only true for create endpoint\n+\n+    def get_id(self) -> int:\n+        \"\"\"Returns the id of the resource. This override deals with\n+        the fact that either an `id` or a `target_project_id` attribute\n+        is returned by the server depending on the endpoint called.\"\"\"\n+        target_project_id = cast(int, super().get_id())\n+        if target_project_id is not None:\n+            return target_project_id\n+        return cast(int, self.id)\n+\n+\n+class AllowlistProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):\n+    _path = \"/projects/{project_id}/job_token_scope/allowlist\"\n+    _obj_cls = AllowlistProject\n+    _from_parent_attrs = {\"project_id\": \"project_id\"}\n+    _create_attrs = RequiredOptional(required=(\"target_project_id\",))\n+\n+\n+class AllowlistGroup(ObjectDeleteMixin, RESTObject):\n+    _id_attr = \"target_group_id\"  # note: only true for create endpoint\n+\n+    def get_id(self) -> int:\n+        \"\"\"Returns the id of the resource. This override deals with\n+        the fact that either an `id` or a `target_group_id` attribute\n+        is returned by the server depending on the endpoint called.\"\"\"\n+        target_group_id = cast(int, super().get_id())\n+        if target_group_id is not None:\n+            return target_group_id\n+        return cast(int, self.id)\n+\n+\n+class AllowlistGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):\n+    _path = \"/projects/{project_id}/job_token_scope/groups_allowlist\"\n+    _obj_cls = AllowlistGroup\n+    _from_parent_attrs = {\"project_id\": \"project_id\"}\n+    _create_attrs = RequiredOptional(required=(\"target_group_id\",))\n", "issue": "Support /projects/:id/job_token_scope/allowlist\nI would like to access the job token allow list through the Gitlab API. \r\n\r\nDocs: \r\n- [Get a project\u2019s CI/CD job token inbound allowlist](https://docs.gitlab.com/ee/api/project_job_token_scopes.html#get-a-projects-cicd-job-token-inbound-allowlist)\r\n- [Allow access to your project with a job token](https://docs.gitlab.com/ee/ci/jobs/ci_job_token.html#allow-access-to-your-project-with-a-job-token)\r\n\r\nAPI endpoint: \r\n```\r\nGET/POST/DELETE /projects/:id/job_token_scope/allowlist\r\n```\r\n\r\nI currently have the following manager to access the job token scope allow list:\r\n\r\n```\r\nclass ProjectJobTokenScopeAllowlistManager(\r\n    gitlab.mixins.ListMixin,\r\n    gitlab.mixins.CreateMixin,\r\n    gitlab.mixins.DeleteMixin,\r\n    gitlab.base.RESTManager,\r\n):\r\n    _path = \"/projects/{project_id}/job_token_scope/allowlist\"\r\n    _obj_cls = gitlab.v4.objects.Project\r\n    _from_parent_attrs = {\"project_id\": \"id\"}\r\n    _create_attrs = gitlab.types.RequiredOptional(required=(\"target_project_id\",))\r\n```\n", "before_files": [{"content": "from typing import Any, cast\n\nfrom gitlab.base import RESTManager, RESTObject\nfrom gitlab.mixins import (\n    GetWithoutIdMixin,\n    RefreshMixin,\n    SaveMixin,\n    UpdateMethod,\n    UpdateMixin,\n)\n\n__all__ = [\n    \"ProjectJobTokenScope\",\n    \"ProjectJobTokenScopeManager\",\n]\n\n\nclass ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject):\n    _id_attr = None\n\n\nclass ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):\n    _path = \"/projects/{project_id}/job_token_scope\"\n    _obj_cls = ProjectJobTokenScope\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _update_method = UpdateMethod.PATCH\n\n    def get(self, **kwargs: Any) -> ProjectJobTokenScope:\n        return cast(ProjectJobTokenScope, super().get(**kwargs))\n", "path": "gitlab/v4/objects/job_token_scope.py"}], "after_files": [{"content": "from typing import Any, cast\n\nfrom gitlab.base import RESTManager, RESTObject\nfrom gitlab.mixins import (\n    CreateMixin,\n    DeleteMixin,\n    GetWithoutIdMixin,\n    ListMixin,\n    ObjectDeleteMixin,\n    RefreshMixin,\n    SaveMixin,\n    UpdateMethod,\n    UpdateMixin,\n)\nfrom gitlab.types import RequiredOptional\n\n__all__ = [\n    \"ProjectJobTokenScope\",\n    \"ProjectJobTokenScopeManager\",\n]\n\n\nclass ProjectJobTokenScope(RefreshMixin, SaveMixin, RESTObject):\n    _id_attr = None\n\n    allowlist: \"AllowlistProjectManager\"\n    groups_allowlist: \"AllowlistGroupManager\"\n\n\nclass ProjectJobTokenScopeManager(GetWithoutIdMixin, UpdateMixin, RESTManager):\n    _path = \"/projects/{project_id}/job_token_scope\"\n    _obj_cls = ProjectJobTokenScope\n    _from_parent_attrs = {\"project_id\": \"id\"}\n    _update_method = UpdateMethod.PATCH\n\n    def get(self, **kwargs: Any) -> ProjectJobTokenScope:\n        return cast(ProjectJobTokenScope, super().get(**kwargs))\n\n\nclass AllowlistProject(ObjectDeleteMixin, RESTObject):\n    _id_attr = \"target_project_id\"  # note: only true for create endpoint\n\n    def get_id(self) -> int:\n        \"\"\"Returns the id of the resource. This override deals with\n        the fact that either an `id` or a `target_project_id` attribute\n        is returned by the server depending on the endpoint called.\"\"\"\n        target_project_id = cast(int, super().get_id())\n        if target_project_id is not None:\n            return target_project_id\n        return cast(int, self.id)\n\n\nclass AllowlistProjectManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):\n    _path = \"/projects/{project_id}/job_token_scope/allowlist\"\n    _obj_cls = AllowlistProject\n    _from_parent_attrs = {\"project_id\": \"project_id\"}\n    _create_attrs = RequiredOptional(required=(\"target_project_id\",))\n\n\nclass AllowlistGroup(ObjectDeleteMixin, RESTObject):\n    _id_attr = \"target_group_id\"  # note: only true for create endpoint\n\n    def get_id(self) -> int:\n        \"\"\"Returns the id of the resource. This override deals with\n        the fact that either an `id` or a `target_group_id` attribute\n        is returned by the server depending on the endpoint called.\"\"\"\n        target_group_id = cast(int, super().get_id())\n        if target_group_id is not None:\n            return target_group_id\n        return cast(int, self.id)\n\n\nclass AllowlistGroupManager(ListMixin, CreateMixin, DeleteMixin, RESTManager):\n    _path = \"/projects/{project_id}/job_token_scope/groups_allowlist\"\n    _obj_cls = AllowlistGroup\n    _from_parent_attrs = {\"project_id\": \"project_id\"}\n    _create_attrs = RequiredOptional(required=(\"target_group_id\",))\n", "path": "gitlab/v4/objects/job_token_scope.py"}]}