Skip to content

Commit

Permalink
GitHub Users API (#909)
Browse files Browse the repository at this point in the history
* Sort GitHub API properties alphabetically

* Add: Add most important parts of the GitHub users REST API

We want to be able to get information about the users and their login
information.
  • Loading branch information
bjoernricks authored Oct 23, 2023
1 parent 054c3b4 commit 12f710a
Show file tree
Hide file tree
Showing 5 changed files with 701 additions and 6 deletions.
20 changes: 14 additions & 6 deletions pontos/github/api/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
from pontos.github.api.secret_scanning import GitHubAsyncRESTSecretScanning
from pontos.github.api.tags import GitHubAsyncRESTTags
from pontos.github.api.teams import GitHubAsyncRESTTeams
from pontos.github.api.users import GitHubAsyncRESTUsers
from pontos.github.api.workflows import GitHubAsyncRESTWorkflows
from pontos.helper import deprecated

Expand Down Expand Up @@ -95,6 +96,13 @@ def branches(self) -> GitHubAsyncRESTBranches:
"""
return GitHubAsyncRESTBranches(self._client)

@property
def code_scanning(self) -> GitHubAsyncRESTCodeScanning:
"""
Code scanning related API
"""
return GitHubAsyncRESTCodeScanning(self._client)

@property
def contents(self) -> GitHubAsyncRESTContent:
"""
Expand Down Expand Up @@ -168,11 +176,11 @@ def secret_scanning(self) -> GitHubAsyncRESTSecretScanning:
return GitHubAsyncRESTSecretScanning(self._client)

@property
def code_scanning(self) -> GitHubAsyncRESTCodeScanning:
def search(self) -> GitHubAsyncRESTSearch:
"""
Code scanning related API
Search related API
"""
return GitHubAsyncRESTCodeScanning(self._client)
return GitHubAsyncRESTSearch(self._client)

@property
def teams(self) -> GitHubAsyncRESTTeams:
Expand All @@ -189,11 +197,11 @@ def tags(self) -> GitHubAsyncRESTTags:
return GitHubAsyncRESTTags(self._client)

@property
def search(self) -> GitHubAsyncRESTSearch:
def users(self) -> GitHubAsyncRESTUsers:
"""
Search related API
Users related API
"""
return GitHubAsyncRESTSearch(self._client)
return GitHubAsyncRESTUsers(self._client)

async def __aenter__(self) -> "GitHubAsyncRESTApi":
await self._client.__aenter__()
Expand Down
289 changes: 289 additions & 0 deletions pontos/github/api/users.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
# SPDX-FileCopyrightText: 2023 Greenbone AG
#
# SPDX-License-Identifier: GPL-3.0-or-later

from typing import AsyncIterator, Union

from pontos.github.api.client import GitHubAsyncREST
from pontos.github.api.helper import JSON_OBJECT
from pontos.github.models.base import User
from pontos.github.models.user import (
EmailInformation,
SSHPublicKey,
SSHPublicKeyExtended,
)


class GitHubAsyncRESTUsers(GitHubAsyncREST):
async def users(self) -> AsyncIterator[User]:
"""
https://docs.github.com/en/rest/users/users#list-users
Args:
username: The handle for the GitHub user account
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
An async iterator yielding user information
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
async for user in api.users.users():
print(user)
"""
api = "/users"
params = {"per_page": "100"}
async for response in self._client.get_all(api, params=params):
response.raise_for_status()

for user in response.json():
yield User.from_dict(user)

async def user(self, username: str) -> User:
"""
Provide publicly available information about someone with a GitHub
account
https://docs.github.com/en/rest/users/users#get-a-user
Args:
username: The handle for the GitHub user account
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
Information about the user
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
user = await api.users.user("foo")
print(user)
"""
api = f"/users/{username}"
response = await self._client.get(api)
response.raise_for_status()
return User.from_dict(response.json())

async def current_user(self) -> User:
"""
Get the current authenticated user
https://docs.github.com/en/rest/users/users#get-the-authenticated-user
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
Information about the user
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
user = await api.users.current_user()
print(user)
"""
api = "/user"
response = await self._client.get(api)
response.raise_for_status()
return User.from_dict(response.json())

async def user_keys(self, username: str) -> AsyncIterator[SSHPublicKey]:
"""
List the verified public SSH keys for a user
https://docs.github.com/en/rest/users/keys#list-public-keys-for-a-user
Args:
username: The handle for the GitHub user account
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
An async iterator yielding ssh key information
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
async for key in api.users.user_keys("foo"):
print(key)
"""
api = f"/users/{username}/keys"
params = {"per_page": "100"}
async for response in self._client.get_all(api, params=params):
response.raise_for_status()

for key in response.json():
yield SSHPublicKey.from_dict(key)

async def keys(self) -> AsyncIterator[SSHPublicKey]:
"""
List the public SSH keys for the authenticated user's GitHub account
https://docs.github.com/en/rest/users/keys#list-public-ssh-keys-for-the-authenticated-user
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
An async iterator yielding ssh key information
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
async for key in api.users.keys():
print(key)
"""
api = "/user/keys"
params = {"per_page": "100"}
async for response in self._client.get_all(api, params=params):
response.raise_for_status()

for key in response.json():
yield SSHPublicKey.from_dict(key)

async def emails(self) -> AsyncIterator[EmailInformation]:
"""
List all email addresses of the currently logged in user
https://docs.github.com/en/rest/users/emails#list-email-addresses-for-the-authenticated-user
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
An async iterator yielding email information
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
async for email in api.users.emails():
print(email)
"""
api = "/user/emails"
params = {"per_page": "100"}
async for response in self._client.get_all(api, params=params):
response.raise_for_status()

for email in response.json():
yield EmailInformation.from_dict(email)

async def key(self, key_id: Union[str, int]) -> SSHPublicKeyExtended:
"""
View extended details for a single public SSH key
https://docs.github.com/en/rest/users/keys#get-a-public-ssh-key-for-the-authenticated-user
Args:
key_id: The unique identifier of the key
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
Extended information about the SSH key
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
key = await api.users.key(123)
print(key)
"""
api = f"/user/keys/{key_id}"
response = await self._client.get(api)
response.raise_for_status()
return SSHPublicKeyExtended.from_dict(response.json())

async def delete_key(self, key_id: Union[str, int]) -> None:
"""
Removes a public SSH key from the authenticated user's GitHub account
https://docs.github.com/en/rest/users/keys#delete-a-public-ssh-key-for-the-authenticated-user
Args:
key_id: The unique identifier of the key
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
await api.users.delete_key(123)
"""
api = f"/user/keys/{key_id}"
response = await self._client.delete(api)
response.raise_for_status()

async def create_key(self, title: str, key: str) -> SSHPublicKeyExtended:
"""
Adds a public SSH key to the authenticated user's GitHub account
https://docs.github.com/en/rest/users/keys#create-a-public-ssh-key-for-the-authenticated-user
Args:
title: A descriptive name for the new key
key: The public SSH key to add to your GitHub account
Raises:
HTTPStatusError: A httpx.HTTPStatusError is raised if the request
failed.
Returns:
Extended information about the SSH key
Example:
.. code-block:: python
from pontos.github.api import GitHubAsyncRESTApi
async with GitHubAsyncRESTApi(token) as api:
key = await api.users.create_key(
"My SSH Public Key",
"2Sg8iYjAxxmI2LvUXpJjkYrMxURPc8r+dB7TJyvv1234"
)
print(key)
"""
api = "/user/keys"
data: JSON_OBJECT = {"key": key, "title": title}
response = await self._client.post(api, data=data)
response.raise_for_status()
return SSHPublicKeyExtended.from_dict(response.json())
Loading

0 comments on commit 12f710a

Please sign in to comment.