diff options
author | Nejc Habjan <hab.nejc@gmail.com> | 2021-09-12 20:58:31 +0200 |
---|---|---|
committer | Nejc Habjan <hab.nejc@gmail.com> | 2021-09-13 08:55:22 +0200 |
commit | 4e8e4b4101059eee43c4c012b131355428ebc4f7 (patch) | |
tree | 17a058762552947a2c79757ed2e31b4a08050386 | |
parent | ce4bc0daef355e2d877360c6e496c23856138872 (diff) | |
download | gitlab-feat/create-delete-token.tar.gz |
feat(objects): support Create and Revoke personal access token APIfeat/create-delete-token
-rw-r--r-- | docs/gl_objects/personal_access_tokens.rst | 32 | ||||
-rw-r--r-- | gitlab/v4/objects/personal_access_tokens.py | 23 | ||||
-rw-r--r-- | gitlab/v4/objects/users.py | 2 | ||||
-rw-r--r-- | tests/unit/objects/test_personal_access_tokens.py | 90 |
4 files changed, 119 insertions, 28 deletions
diff --git a/docs/gl_objects/personal_access_tokens.rst b/docs/gl_objects/personal_access_tokens.rst index 3cbc744..0704c75 100644 --- a/docs/gl_objects/personal_access_tokens.rst +++ b/docs/gl_objects/personal_access_tokens.rst @@ -2,8 +2,6 @@ Personal Access Tokens ###################### -Get a list of personal access tokens - References ---------- @@ -12,8 +10,14 @@ References + :class:`gitlab.v4.objects.PersonalAccessToken` + :class:`gitlab.v4.objects.PersonalAcessTokenManager` + :attr:`gitlab.Gitlab.personal_access_tokens` + + :class:`gitlab.v4.objects.UserPersonalAccessToken` + + :class:`gitlab.v4.objects.UserPersonalAcessTokenManager` + + :attr:`gitlab.Gitlab.User.personal_access_tokens` + +* GitLab API: -* GitLab API: https://docs.gitlab.com/ee/api/personal_access_tokens.html + + https://docs.gitlab.com/ee/api/personal_access_tokens.html + + https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token Examples -------- @@ -26,3 +30,25 @@ List personal access tokens:: List personal access tokens from other user_id (admin only):: access_tokens = gl.personal_access_tokens.list(user_id=25) + +Revoke a personal access token fetched via list:: + + access_token = access_tokens[0] + access_token.delete() + +Revoke a personal access token by id:: + + gl.personal_access_tokens.delete(123) + +Create a personal access token for a user (admin only):: + + user = gl.users.get(25, lazy=True) + access_token = user.personal_access_tokens.create({"name": "test", "scopes": "api"}) + +.. note:: As you can see above, you can only create personal access tokens + via the Users API, but you cannot revoke these objects directly. + This is because the create API uses a different endpoint than the list and revoke APIs. + You need to fetch the token via the list API first to revoke it. + + As of 14.2, GitLab does not provide a GET API for single personal access tokens. + You must use the list method to retrieve single tokens. diff --git a/gitlab/v4/objects/personal_access_tokens.py b/gitlab/v4/objects/personal_access_tokens.py index a326bd6..6cdb305 100644 --- a/gitlab/v4/objects/personal_access_tokens.py +++ b/gitlab/v4/objects/personal_access_tokens.py @@ -1,17 +1,32 @@ -from gitlab.base import RESTManager, RESTObject -from gitlab.mixins import ListMixin +from gitlab.base import RequiredOptional, RESTManager, RESTObject +from gitlab.mixins import CreateMixin, DeleteMixin, ListMixin, ObjectDeleteMixin __all__ = [ "PersonalAccessToken", "PersonalAccessTokenManager", + "UserPersonalAccessToken", + "UserPersonalAccessTokenManager", ] -class PersonalAccessToken(RESTObject): +class PersonalAccessToken(ObjectDeleteMixin, RESTObject): pass -class PersonalAccessTokenManager(ListMixin, RESTManager): +class PersonalAccessTokenManager(DeleteMixin, ListMixin, RESTManager): _path = "/personal_access_tokens" _obj_cls = PersonalAccessToken _list_filters = ("user_id",) + + +class UserPersonalAccessToken(RESTObject): + pass + + +class UserPersonalAccessTokenManager(CreateMixin, RESTManager): + _path = "/users/%(user_id)s/personal_access_tokens" + _obj_cls = UserPersonalAccessToken + _from_parent_attrs = {"user_id": "id"} + _create_attrs = RequiredOptional( + required=("name", "scopes"), optional=("expires_at",) + ) diff --git a/gitlab/v4/objects/users.py b/gitlab/v4/objects/users.py index c0f8745..63da837 100644 --- a/gitlab/v4/objects/users.py +++ b/gitlab/v4/objects/users.py @@ -17,6 +17,7 @@ from gitlab.mixins import ( from .custom_attributes import UserCustomAttributeManager # noqa: F401 from .events import UserEventManager # noqa: F401 +from .personal_access_tokens import UserPersonalAccessTokenManager # noqa: F401 __all__ = [ "CurrentUserEmail", @@ -122,6 +123,7 @@ class User(SaveMixin, ObjectDeleteMixin, RESTObject): impersonationtokens: "UserImpersonationTokenManager" keys: "UserKeyManager" memberships: "UserMembershipManager" + personal_access_tokens: UserPersonalAccessTokenManager projects: "UserProjectManager" status: "UserStatusManager" diff --git a/tests/unit/objects/test_personal_access_tokens.py b/tests/unit/objects/test_personal_access_tokens.py index 920cb1d..065b5c8 100644 --- a/tests/unit/objects/test_personal_access_tokens.py +++ b/tests/unit/objects/test_personal_access_tokens.py @@ -1,46 +1,94 @@ """ -GitLab API: https://docs.gitlab.com/ee/api/personal_access_tokens.html +GitLab API: +https://docs.gitlab.com/ee/api/personal_access_tokens.html +https://docs.gitlab.com/ee/api/users.html#create-a-personal-access-token """ import pytest import responses +user_id = 1 +token_id = 1 +token_name = "Test Token" + +token_url = "http://localhost/api/v4/personal_access_tokens" +single_token_url = f"{token_url}/{token_id}" +user_token_url = f"http://localhost/api/v4/users/{user_id}/personal_access_tokens" + +content = { + "id": token_id, + "name": token_name, + "revoked": False, + "created_at": "2020-07-23T14:31:47.729Z", + "scopes": ["api"], + "active": True, + "user_id": user_id, + "expires_at": None, +} + @pytest.fixture -def resp_list_personal_access_token(): - content = [ - { - "id": 4, - "name": "Test Token", - "revoked": False, - "created_at": "2020-07-23T14:31:47.729Z", - "scopes": ["api"], - "active": True, - "user_id": 24, - "expires_at": None, - } - ] +def resp_create_user_personal_access_token(): + with responses.RequestsMock() as rsps: + rsps.add( + method=responses.POST, + url=user_token_url, + json=content, + content_type="application/json", + status=200, + ) + yield rsps + +@pytest.fixture +def resp_personal_access_token(no_content): with responses.RequestsMock(assert_all_requests_are_fired=False) as rsps: rsps.add( method=responses.GET, - url="http://localhost/api/v4/personal_access_tokens", - json=content, + url=token_url, + json=[content], content_type="application/json", status=200, ) + rsps.add( + method=responses.DELETE, + url=single_token_url, + json=no_content, + content_type="application/json", + status=204, + ) yield rsps -def test_list_personal_access_tokens(gl, resp_list_personal_access_token): +def test_create_personal_access_token(gl, resp_create_user_personal_access_token): + user = gl.users.get(1, lazy=True) + access_token = user.personal_access_tokens.create( + {"name": token_name, "scopes": "api"} + ) + assert access_token.revoked is False + assert access_token.name == token_name + + +def test_list_personal_access_tokens(gl, resp_personal_access_token): access_tokens = gl.personal_access_tokens.list() assert len(access_tokens) == 1 assert access_tokens[0].revoked is False - assert access_tokens[0].name == "Test Token" + assert access_tokens[0].name == token_name -def test_list_personal_access_tokens_filter(gl, resp_list_personal_access_token): - access_tokens = gl.personal_access_tokens.list(user_id=24) +def test_list_personal_access_tokens_filter(gl, resp_personal_access_token): + access_tokens = gl.personal_access_tokens.list(user_id=user_id) assert len(access_tokens) == 1 assert access_tokens[0].revoked is False - assert access_tokens[0].user_id == 24 + assert access_tokens[0].user_id == user_id + + +def test_revoke_personal_access_token(gl, resp_personal_access_token): + access_token = gl.personal_access_tokens.list(user_id=user_id)[0] + access_token.delete() + assert resp_personal_access_token.assert_call_count(single_token_url, 1) + + +def test_revoke_personal_access_token_by_id(gl, resp_personal_access_token): + gl.personal_access_tokens.delete(token_id) + assert resp_personal_access_token.assert_call_count(single_token_url, 1) |