Skip to content

Commit fff966d

Browse files
🩹 [Patch]: Add Fine-Grained Permissions Data for GitHub PowerShell Module (#501)
This PR implements a comprehensive fine-grained permissions data infrastructure for the GitHub PowerShell module, enabling detection of GitHub App installations that may be missing newly added permissions. - Fixes #485 ## What's New ### GitHubPermission Class Added a new public `GitHubPermission` class with the following properties: - **Name** - Programmatic permission name (e.g., `contents`, `issues`) - **DisplayName** - Human-friendly name (e.g., "Contents", "Issues") - **Description** - Brief description of what access the permission grants - **URL** - Link to relevant GitHub documentation - **Options** - Available access levels (`read`, `write`, `admin`) - **Type** - Permission type (`Fine-grained`, `Classic`) - **Scope** - Application scope (`Repository`, `Organization`, `User`, `Enterprise`) ### Comprehensive Permissions Database Added 90 fine-grained permissions covering all major GitHub permission categories: - **33 Repository permissions** - actions, contents, issues, pull_requests, secrets, etc. - **33 Organization permissions** - members, administration, organization_secrets, etc. - **18 User permissions** - profile, followers, git_ssh_keys, etc. - **6 Enterprise permissions** - custom properties, organization installation, etc. ### Get-GitHubPermissionDefinition Function New public function to query the permissions database with advanced filtering: ```powershell # Get all permissions Get-GitHubPermissionDefinition # Filter by scope Get-GitHubPermissionDefinition -Scope Repository # Combined filtering Get-GitHubPermissionDefinition -Type Fine-grained -Scope Organization # Find specific permissions Get-GitHubPermissionDefinition -Name 'contents' ``` ### Argument Completers Added argument completers for `Get-GitHubPermissionDefinition` parameters to improve user experience: - **Name** - Tab completion for available permission names (actions, contents, issues, etc.) - **DisplayName** - Tab completion for available permission display names (Actions, Dependabot alerts, etc.) - **Type** - Tab completion for available permission types (Fine-grained) - **Scope** - Tab completion for available scopes (Repository, Organization, User, Enterprise) ## Use Cases This infrastructure enables several key scenarios: 1. **Permission Validation** - Compare GitHub App installations against the complete permissions list 2. **Installation Health Checks** - Detect apps missing newly added permissions 3. **Documentation** - Provide users with comprehensive permission reference 4. **Automation** - Build tools that ensure installations stay current with permission requirements 5. **Enhanced User Experience** - Tab completion for parameter values improves usability ## Implementation Details - **File path permissions excluded** - These are handled differently by the GitHub API (appear under `FilePaths` property rather than as named permissions) - **Maintainable structure** - Easy to update when GitHub adds new permissions - **Performance optimized** - Efficient filtering and lookup operations - **Comprehensive testing** - Full test coverage for all functionality - **Argument completion** - Improves user experience with tab completion support ## Example Usage ```powershell # Check what repository permissions are available (with tab completion) $repoPerms = Get-GitHubPermissionDefinition -Scope <TAB> Write-Host "Repository permissions: $($repoPerms.Count)" # Get details about the contents permission (with tab completion) $contents = Get-GitHubPermissionDefinition -Name cont<TAB> Write-Host "$($contents.DisplayName): $($contents.Description)" Write-Host "Available options: $($contents.Options -join ', ')" ``` This provides the foundation for building automated permission management tools and ensuring GitHub App installations remain up-to-date with the latest permission requirements. --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: MariusStorhaug <17722253+MariusStorhaug@users.noreply.github.com> Co-authored-by: Marius Storhaug <marstor@hotmail.com>
1 parent 9e7a331 commit fff966d

File tree

6 files changed

+1622
-0
lines changed

6 files changed

+1622
-0
lines changed
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
class GitHubPermissionDefinition {
2+
# The programmatic name of the permission as returned by the GitHub API
3+
[string] $Name
4+
5+
# The human-friendly name of the permission as shown in the GitHub UI
6+
[string] $DisplayName
7+
8+
# A brief description of what access the permission grants
9+
[string] $Description
10+
11+
# A link to the relevant documentation or GitHub UI page
12+
[uri] $URL
13+
14+
# The levels of access that can be granted for this permission
15+
[string[]] $Options
16+
17+
# The type of permission (Fine-grained, Classic)
18+
[string] $Type
19+
20+
# The scope at which this permission applies (Repository, Organization, User, Enterprise)
21+
[string] $Scope
22+
23+
GitHubPermissionDefinition() {}
24+
25+
GitHubPermissionDefinition(
26+
[string]$Name,
27+
[string]$DisplayName,
28+
[string]$Description,
29+
[string]$URL,
30+
[string[]]$Options,
31+
[string]$Type,
32+
[string]$Scope
33+
) {
34+
$this.Name = $Name
35+
$this.DisplayName = $DisplayName
36+
$this.Description = $Description
37+
$this.URL = [uri]$URL
38+
$this.Options = $Options
39+
$this.Type = $Type
40+
$this.Scope = $Scope
41+
}
42+
43+
[string] ToString() {
44+
return $this.Name
45+
}
46+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Configuration>
3+
<ViewDefinitions>
4+
<View>
5+
<Name>GitHubPermissionDefinitionTable</Name>
6+
<ViewSelectedBy>
7+
<TypeName>GitHubPermissionDefinition</TypeName>
8+
</ViewSelectedBy>
9+
<TableControl>
10+
<TableHeaders>
11+
<TableColumnHeader>
12+
<Label>Scope</Label>
13+
</TableColumnHeader>
14+
<TableColumnHeader>
15+
<Label>DisplayName</Label>
16+
</TableColumnHeader>
17+
<TableColumnHeader>
18+
<Label>Description</Label>
19+
</TableColumnHeader>
20+
</TableHeaders>
21+
<TableRowEntries>
22+
<TableRowEntry>
23+
<TableColumnItems>
24+
<TableColumnItem>
25+
<PropertyName>Scope</PropertyName>
26+
</TableColumnItem>
27+
<TableColumnItem>
28+
<ScriptBlock>
29+
if ($Host.UI.SupportsVirtualTerminal -and
30+
($env:GITHUB_ACTIONS -ne 'true') -and $_.Url) {
31+
$PSStyle.FormatHyperlink($_.DisplayName, $_.Url)
32+
} else {
33+
$_.DisplayName
34+
}
35+
</ScriptBlock>
36+
</TableColumnItem>
37+
<TableColumnItem>
38+
<PropertyName>Description</PropertyName>
39+
</TableColumnItem>
40+
</TableColumnItems>
41+
</TableRowEntry>
42+
</TableRowEntries>
43+
</TableControl>
44+
</View>
45+
</ViewDefinitions>
46+
</Configuration>
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
function Get-GitHubPermissionDefinition {
2+
<#
3+
.SYNOPSIS
4+
Retrieves GitHub permission definitions
5+
6+
.DESCRIPTION
7+
Gets the list of GitHub permission definitions from the module's internal data store.
8+
This includes fine-grained permissions for repositories, organizations, and user accounts.
9+
The function supports filtering by permission type and scope to help you find specific permissions.
10+
11+
File path-specific permissions are excluded from this list as they are handled differently
12+
by the GitHub API (they appear under the FilePaths property in installation data rather
13+
than as named permissions).
14+
15+
.EXAMPLE
16+
Get-GitHubPermissionDefinition
17+
18+
Gets all permission definitions.
19+
20+
.EXAMPLE
21+
Get-GitHubPermissionDefinition -Type Fine-grained
22+
23+
Gets all fine-grained permission definitions.
24+
25+
.EXAMPLE
26+
Get-GitHubPermissionDefinition -Scope Repository
27+
28+
Gets all permission definitions that apply to repository scope.
29+
30+
.EXAMPLE
31+
Get-GitHubPermissionDefinition -Type Fine-grained -Scope Organization
32+
33+
Gets all fine-grained permission definitions that apply to organization scope.
34+
35+
.EXAMPLE
36+
Get-GitHubPermissionDefinition -Name contents
37+
38+
Gets the specific permission definition for 'contents' permission.
39+
40+
.NOTES
41+
This function provides access to a curated list of GitHub permission definitions maintained within the module.
42+
The data includes permission names, display names, descriptions, available options, and scopes.
43+
44+
File path permissions are excluded from this list as they are handled differently by the GitHub API.
45+
These permissions are user-specified paths with read/write access that appear in the FilePaths
46+
property of GitHub App installation data, not as standard named permissions.
47+
48+
.LINK
49+
https://psmodule.io/GitHub/Functions/Permission/Get-GitHubPermissionDefinition
50+
#>
51+
[OutputType([GitHubPermissionDefinition[]])]
52+
[CmdletBinding()]
53+
param(
54+
# Filter by permission name (supports multiple values & wildcards)
55+
[Parameter()]
56+
[string[]] $Name = '*',
57+
58+
# Filter by permission display name (supports multiple values & wildcards)
59+
[Parameter()]
60+
[string[]] $DisplayName = '*',
61+
62+
# Filter by permission type (supports multiple values & wildcards)
63+
[Parameter()]
64+
[string[]] $Type = '*',
65+
66+
# Filter by permission scope (supports multiple values & wildcards)
67+
[Parameter()]
68+
[string[]] $Scope = '*'
69+
)
70+
71+
begin {
72+
$stackPath = Get-PSCallStackPath
73+
Write-Debug "[$stackPath] - Start"
74+
}
75+
76+
process {
77+
try {
78+
[scriptblock]$test = {
79+
param(
80+
[Parameter(Mandatory)][string] $Value,
81+
[Parameter(Mandatory)][string[]] $Patterns
82+
)
83+
foreach ($p in $Patterns) {
84+
if ($Value -like $p) { return $true }
85+
}
86+
return $false
87+
}
88+
89+
$script:GitHub.Permissions | Where-Object {
90+
(& $test -Value $_.Name -Patterns $Name) -and
91+
(& $test -Value $_.DisplayName -Patterns $DisplayName) -and
92+
(& $test -Value $_.Type -Patterns $Type) -and
93+
(& $test -Value $_.Scope -Patterns $Scope)
94+
}
95+
} catch {
96+
Write-Error "Failed to retrieve GitHub permission definitions: $($_.Exception.Message)"
97+
throw
98+
}
99+
}
100+
101+
end {
102+
Write-Debug "[$stackPath] - End"
103+
}
104+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -ParameterName Name -ScriptBlock {
2+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
3+
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
4+
5+
$script:GitHub.Permissions.Name | Sort-Object -Unique | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
6+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
7+
}
8+
}
9+
10+
Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -ParameterName DisplayName -ScriptBlock {
11+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
12+
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
13+
14+
$script:GitHub.Permissions.DisplayName | Sort-Object -Unique | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
15+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
16+
}
17+
}
18+
19+
Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -ParameterName Type -ScriptBlock {
20+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
21+
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
22+
23+
$script:GitHub.Permissions.Type | Sort-Object -Unique | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
24+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
25+
}
26+
}
27+
28+
Register-ArgumentCompleter -CommandName Get-GitHubPermissionDefinition -ParameterName Scope -ScriptBlock {
29+
param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters)
30+
$null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters
31+
32+
$script:GitHub.Permissions.Scope | Sort-Object -Unique | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
33+
[System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
34+
}
35+
}

0 commit comments

Comments
 (0)