Skip to content

Instantly share code, notes, and snippets.

@lukpueh
Last active January 14, 2021 14:50
Show Gist options
  • Save lukpueh/42c23c35c7cc23ab194bda2db39779bf to your computer and use it in GitHub Desktop.
Save lukpueh/42c23c35c7cc23ab194bda2db39779bf to your computer and use it in GitHub Desktop.
Query GitHub REST API to get org permission for people and teams.
#!/usr/bin/env python
"""Query GitHub REST API to get org permission for people and teams
Usage:
./gh_org_info.py <GitHub user name> <AuthToken> <organization name>
Note: To create an authentication token see
https://docs.github.com/en/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token
Result:
{
"people": {
"<user name>": {
"role": "<one of 'owner', 'member', 'outside collaborator'>",
"repos": {
"<repository name>": {
"permission": ["<(admin|push|maintain|triage|pull)>", ...]
}, ...
},
}, ...
},
"teams": {
"<team name>": {
"members": [
<username>, ...
],
"repos": {
"<repository name>": {
"permission": ["<(admin|push|maintain|triage|pull)>", ...],
}, ...
}
}, ...
},
"repos": ["<repository name>", ...]
}
"""
import sys
import json
import requests
def get_info(login, token, org):
"""Get GitHub organization info about people and teams permissions. """
def _get(endpoint):
"""Query API and error if result is not a list. """
url = f"https://api.github.com/{endpoint}"
result = requests.get(url, auth=(login, token))
if result.status_code != requests.codes.ok:
raise Exception(f"request: {url}, response: {result.json()}")
return result.json()
# Init data structure to be returned
org_info = {"people": {}, "teams": {}, "repos": []}
# Temporary list of outside contributors to distinguish from members below
# https://docs.github.com/en/free-pro-team@latest/rest/reference/orgs#list-outside-collaborators-for-an-organization
_org_outside_collaborators = [r['login']
for r in _get(f"orgs/{org}/outside_collaborators")]
# Get people info
# https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#list-organization-repositories
for repo in _get(f"orgs/{org}/repos"):
org_info["repos"].append(repo['name'])
# https://docs.github.com/en/free-pro-team@latest/rest/reference/repos#list-repository-collaborators
for user in _get(f"repos/{org}/{repo['name']}/collaborators"):
user_name = user["login"]
repo_data = {
"permissions": [k for k, v in user["permissions"].items() if v]
}
# Add repo data to existing collaborator entry
if org_info["people"].get(user_name):
org_info["people"][user_name]["repos"][repo["name"]] = repo_data
# Create new collaborator entry with intial repo data
else:
# Query collaborator role info (only available for members)
if user_name not in _org_outside_collaborators:
# https://docs.github.com/en/free-pro-team@latest/rest/reference/orgs#get-organization-membership-for-a-user
member_details = _get(f"orgs/{org}/memberships/{user['login']}")
role = member_details["role"]
else:
role = "outside collaborator"
# Get full name for user
# https://docs.github.com/en/free-pro-team@latest/rest/reference/users#get-a-user
name = _get(f"users/{user_name}").get("name")
org_info["people"][user_name] = {
"name": name,
"repos": {repo["name"]: repo_data},
"role": role
}
# Get teams info
# https://docs.github.com/en/free-pro-team@latest/rest/reference/teams#list-teams
for team in _get(f"orgs/{org}/teams"):
members = []
# https://docs.github.com/en/free-pro-team@latest/rest/reference/teams#list-team-members
for member in _get(f"teams/{team['id']}/members"):
members.append(member["login"])
# https://docs.github.com/en/free-pro-team@latest/rest/reference/teams#list-team-repositories
repos = {}
for repo in _get(f"teams/{team['id']}/repos"):
repos[repo["name"]] = {
"permissions": [k for k, v in repo["permissions"].items() if v]
}
org_info["teams"][team["name"]] = {
"description": team["description"],
"repos": repos,
"members": members,
}
return org_info
def main():
if len(sys.argv) < 4:
print(f"usage: {sys.argv[0]} <GitHub user name> <GitHub AuthToken> <org>")
sys.exit(1)
login = sys.argv[1]
token = sys.argv[2]
org = sys.argv[3]
org_info = get_info(login, token, org)
print(json.dumps(org_info))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment