diff --git a/gh-cli/README.md b/gh-cli/README.md index 63f62eb..ac71ef6 100644 --- a/gh-cli/README.md +++ b/gh-cli/README.md @@ -1345,7 +1345,16 @@ joshjohanning,admin ### get-repository-users-permission-and-source.sh -Returns the permission for everyone who can access the repo and how they access it (direct, team, org) +Returns the permission for everyone who can access a repository and how they access it (direct, team, organization). Uses the REST API to get accurate team role names including maintain, triage, and custom roles. + +Example output: + +```text +USER EFFECTIVE SOURCES +joshjohanning ADMIN org-member(ADMIN), team:admin-team(WRITE), team:approver-team(WRITE) +FluffyCarlton MAINTAIN direct(MAINTAIN), org-member(READ) +joshgoldfishturtle ADMIN org-member(READ), team:compliance-team(ADMIN) +``` ### get-repository.sh diff --git a/gh-cli/get-repository-users-permission-and-source.sh b/gh-cli/get-repository-users-permission-and-source.sh index b24ec24..a3c4680 100755 --- a/gh-cli/get-repository-users-permission-and-source.sh +++ b/gh-cli/get-repository-users-permission-and-source.sh @@ -1,13 +1,74 @@ #!/bin/bash -# gh cli's token needs to be able to admin org - run this first if it can't -# gh auth refresh -h github.com -s admin:org +# Returns the permission for everyone who can access a repository and how they +# access it (direct, team, organization) +# +# Uses the REST API to get accurate team role names (maintain, triage) since the +# GraphQL permissionSources API only returns READ, WRITE, and ADMIN. A heuristic +# is also applied to direct sources to correct MAINTAIN/TRIAGE labels. +# +# gh cli's token needs to be able to admin the organization - run this first if needed: +# gh auth refresh -h github.com -s admin:org +# +# Usage: +# ./get-repository-users-permission-and-source.sh [affiliation] [hostname] +# +# affiliation can be: OUTSIDE, DIRECT, ALL (default: ALL) +# hostname: GitHub hostname (default: github.com), e.g. github.example.com -# affiliation can be: OUTSIDE, DIRECT, ALL +# Example output: +# +# USER EFFECTIVE SOURCES +# joshjohanning ADMIN org-member(ADMIN), team:admin-team(WRITE), team:approver-team(WRITE) +# FluffyCarlton MAINTAIN direct(MAINTAIN), org-member(READ) +# joshgoldfishturtle ADMIN org-member(READ), team:compliance-team(ADMIN) -# returns the permission for everyone who can access the repo and how they access it (direct, team, org) -gh api graphql --paginate -f owner='joshjohanning-org' -f repo='ghas-demo' -f affiliation='ALL' -f query=' +if [ -z "$2" ]; then + echo "Usage: $0 [affiliation] [hostname]" + echo " affiliation: OUTSIDE, DIRECT, ALL (default: ALL)" + echo " hostname: GitHub hostname (default: github.com)" + exit 1 +fi + +org="$1" +repo="$2" +affiliation_input="${3:-ALL}" +affiliation="$(echo "$affiliation_input" | tr '[:lower:]' '[:upper:]')" +hostname="${4:-github.com}" + +case "$affiliation" in + OUTSIDE|DIRECT|ALL) + ;; + *) + echo "Error: invalid affiliation '$affiliation_input'. Must be OUTSIDE, DIRECT, or ALL." + exit 1 + ;; +esac + +# Map REST permission names (pull/push) to GraphQL-style names (READ/WRITE) +map_permission() { + case "$1" in + pull) echo "READ" ;; + triage) echo "TRIAGE" ;; + push) echo "WRITE" ;; + maintain) echo "MAINTAIN" ;; + admin) echo "ADMIN" ;; + *) echo "$1" | tr '[:lower:]' '[:upper:]' ;; + esac +} + +# Get true team permissions via REST API and build a sed command to fix labels +sed_cmd="" +while IFS=$'\t' read -r slug perm; do + mapped=$(map_permission "$perm") + sed_cmd="${sed_cmd}s/team:${slug}\([^)]*\)/team:${slug}(${mapped})/g;" +done <