Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh: Allow setting JupyterHub groups from GitHub teams #739

Closed
wants to merge 2 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions oauthenticator/github.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,14 +126,26 @@ def _userdata_url_default(self):
https://docs.github.com/en/rest/reference/teams#list-teams-for-the-authenticated-user.

Requires `read:org` to be set in `scope`.

Note that authentication state is only be available to a
`post_auth_hook` before being discarded unless configured to be
persisted via `enable_auth_state`. For more information, see
https://jupyterhub.readthedocs.io/en/stable/reference/authenticators.html#authentication-state.
""",
)

populate_groups_from_teams = Bool(
False,
config=True,
help="""
Populates JupyterHub groups from list of GitHub teams the user is a part of.

Requires `read:org` to be set in `scope`.

Requires `manage_groups` to be set to True.
""",
)

# _deprecated_oauth_aliases is used by deprecation logic in OAuthenticator
_deprecated_oauth_aliases = {
"github_client_id": ("client_id", "0.1.0"),
Expand Down Expand Up @@ -224,6 +236,8 @@ async def update_auth_model(self, auth_model):
user_info["email"] = val["email"]
break

# https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user
teams_url = f"{self.github_api}/user/teams?per_page=100"
if self.populate_teams_in_auth_state:
if "read:org" not in self.scope:
# This means the "read:org" scope was not set, and we can't
Expand All @@ -232,11 +246,23 @@ async def update_auth_model(self, auth_model):
"read:org scope is required for populate_teams_in_auth_state functionality to work"
)
else:
# https://docs.github.com/en/rest/teams/teams?apiVersion=2022-11-28#list-teams-for-the-authenticated-user
url = f"{self.github_api}/user/teams?per_page=100"
user_teams = await self._paginated_fetch(url, access_token, token_type)
user_teams = await self._paginated_fetch(
teams_url, access_token, token_type
)
auth_model["auth_state"]["teams"] = user_teams

if self.manage_groups and self.populate_groups_from_teams:
if "read:org" not in self.scope:
# This means the "read:org" scope was not set, and we can't fetch teams
self.log.error(
"read:org scope is required for populate_groups_from_teams functionality to work"
)
else:
user_teams = await self._paginated_fetch(
teams_url, access_token, token_type
)
auth_model["groups"] = user_teams

return auth_model

async def _paginated_fetch(self, api_url, access_token, token_type):
Expand Down