diff --git a/src/GitHub/GitHub.ps1 b/src/GitHub/GitHub.ps1 index 6122c7dd3..a0a45426b 100644 --- a/src/GitHub/GitHub.ps1 +++ b/src/GitHub/GitHub.ps1 @@ -1,14 +1,12 @@ -Write-Verbose "Initializing GitHub module..." -Verbose +$scriptFilePath = $MyInvocation.MyCommand.Path + +Write-Verbose "[$scriptFilePath] - Initializing GitHub module..." -Verbose -$script:Config = $script:ConfigTemplate | ConvertTo-Json -Depth 100 | ConvertFrom-Json Initialize-SecretVault -Name $script:SecretVault.Name -Type $script:SecretVault.Type -Restore-GitHubConfig -if (-not [string]::IsNullOrEmpty($env:GH_TOKEN)) { - Write-Verbose 'Logging on using GH_TOKEN' - Connect-GitHubAccount -AccessToken $env:GH_TOKEN -} -if (-not [string]::IsNullOrEmpty($env:GITHUB_TOKEN)) { - Write-Verbose 'Logging on using GITHUB_TOKEN' - Connect-GitHubAccount -AccessToken $env:GITHUB_TOKEN +# Autologon if a token is present in environment variables +$envVar = Get-ChildItem -Path 'Env:' | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1 +$envVarPresent = $envVar.count -gt 0 +if ($envVarPresent) { + Connect-GitHubAccount } diff --git a/src/GitHub/GitHub.psm1 b/src/GitHub/GitHub.psm1 index bbac83a75..20a13acca 100644 --- a/src/GitHub/GitHub.psm1 +++ b/src/GitHub/GitHub.psm1 @@ -6,28 +6,27 @@ Write-Verbose "[$scriptName] - Importing module" #region - Importing data files Write-Verbose "[$scriptName] - [data] - Processing folder" -$dataFolder = (Join-Path $PSScriptRoot 'data') -Write-Verbose "[$scriptName] - [data] - [$dataFolder]" -Get-ChildItem -Path "$dataFolder" -Recurse -Force -Include '*.psd1' | ForEach-Object { +$dataFolder = Join-Path $PSScriptRoot 'data' +Get-ChildItem -Path $dataFolder -Recurse -Force -Include '*.psd1' -ErrorAction SilentlyContinue | ForEach-Object { Write-Verbose "[$scriptName] - [data] - [$($_.Name)] - Importing data file" New-Variable -Name $_.BaseName -Value (Import-PowerShellDataFile -Path $_.FullName) -Force Write-Verbose "[$scriptName] - [data] - [$($_.Name)] - Done" } Write-Verbose "[$scriptName] - [data] - Done" -#endregion - Importing datas +#endregion - Importing data files #region - Importing script files $folders = 'init', 'classes', 'private', 'public' foreach ($folder in $folders) { Write-Verbose "[$scriptName] - [$folder] - Processing folder" - $folderPath = Join-Path -Path $PSScriptRoot -ChildPath $folder + $folderPath = Join-Path $PSScriptRoot $folder if (Test-Path -Path $folderPath) { - $files = Get-ChildItem -Path $folderPath -Include '*.ps1', '*.psm1' -Recurse | Sort-Object -Property FullName - foreach ($file in $files) { - Write-Verbose "[$scriptName] - [$folder] - [$($file.Name)] - Importing script file" - Import-Module $file -Verbose:$false - Write-Verbose "[$scriptName] - [$folder] - [$($file.Name)] - Done" - } + Get-ChildItem -Path $folderPath -Include '*.ps1', '*.psm1' -Recurse | + Sort-Object -Property FullName | ForEach-Object { + Write-Verbose "[$scriptName] - [$folder] - [$($_.Name)] - Importing script file" + Import-Module $_ -Verbose:$false + Write-Verbose "[$scriptName] - [$folder] - [$($_.Name)] - Done" + } } Write-Verbose "[$scriptName] - [$folder] - Done" } @@ -44,7 +43,7 @@ Write-Verbose "[$scriptName] - [Root] - Done" #endregion - Importing root script files #region Export module members -$foldersToProcess = Get-ChildItem -Path $PSScriptRoot -Directory | Where-Object -Property Name -In $folders +$foldersToProcess = Get-ChildItem -Path $PSScriptRoot -Directory | Where-Object Name -In $folders $moduleFiles = $foldersToProcess | Get-ChildItem -Include '*.ps1' -Recurse -File -Force $functions = $moduleFiles.BaseName $param = @{ @@ -54,9 +53,9 @@ $param = @{ Alias = '*' } -Write-Verbose 'Exporting module members' - +Write-Verbose "[$scriptName] - Exporting module members" Export-ModuleMember @param +Write-Verbose "[$scriptName] - Exporting module members - Done" #endregion Export module members Write-Verbose "[$scriptName] - Done" diff --git a/src/GitHub/data/SecretVault.psd1 b/src/GitHub/data/SecretVault.psd1 index e119766f1..6a669c66a 100644 --- a/src/GitHub/data/SecretVault.psd1 +++ b/src/GitHub/data/SecretVault.psd1 @@ -1,7 +1,5 @@ @{ - Name = 'GitHub' # $script:SecretVault.Name + Name = 'SecretStore' # $script:SecretVault.Name Type = 'Microsoft.PowerShell.SecretStore' # $script:SecretVault.Type - Secret = @{ - Name = 'Config' # $script:SecretVault.Secret.Name - } + Prefix = 'GHPS_' # $script:SecretVault.Prefix } diff --git a/src/GitHub/en_US/about_Config.help.txt b/src/GitHub/en_US/about_Config.help.txt index 315028b52..d6e25c783 100644 --- a/src/GitHub/en_US/about_Config.help.txt +++ b/src/GitHub/en_US/about_Config.help.txt @@ -53,8 +53,6 @@ FUNCTIONS - Get-GitHubConfig: Fetches the current module configuration. - Reset-GitHubConfig: Resets all or specific sections to its default values. - - Restore-GitHubConfig: Restores the configuration from the secret vault. - - Save-GitHubConfig: Saves the current configuration to the secret vault. - Set-GitHubConfig: Allows setting specific elements of the configuration. CONFIGURATION @@ -87,21 +85,10 @@ EXAMPLES -------------------------- EXAMPLE 3 -------------------------- - Restore-GitHubConfig + Reset-GitHubConfig -Scope Auth - This command restores the GitHub configuration from the secret vault. + This command resets the Auth related settings of the GitHub configuration to its default values. - -------------------------- EXAMPLE 4 -------------------------- - - Reset-GitHubConfig -Scope 'App.API' - - This command resets the 'App.API' section of the GitHub configuration to its default values. - - -------------------------- EXAMPLE 5 -------------------------- - - Save-GitHubConfig - - This command saves the current GitHub configuration to the secret vault. KEYWORDS diff --git a/src/GitHub/private/Auth/DeviceFlow/Check-GitHubAccessToken.ps1 b/src/GitHub/private/Auth/DeviceFlow/Check-GitHubAccessToken.ps1 deleted file mode 100644 index 1ef8db1af..000000000 --- a/src/GitHub/private/Auth/DeviceFlow/Check-GitHubAccessToken.ps1 +++ /dev/null @@ -1,12 +0,0 @@ -function Check-GitHubAccessToken { - - [DateTime]$accessTokenExirationDate = $script:Config.User.Auth.AccessToken.ExpirationDate - $accessTokenValid = $accessTokenExirationDate -gt (Get-Date) - - if (-not $accessTokenValid) { - Write-Warning 'Your access token has expired. Refreshing it...' - Connect-GitHubAccount -Refresh - } - $TimeSpan = New-TimeSpan -Start (Get-Date) -End $accessTokenExirationDate - Write-Host "Your access token will expire in $($TimeSpan.Days)-$($TimeSpan.Hours):$($TimeSpan.Minutes):$($TimeSpan.Seconds)." -} diff --git a/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 b/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 index 93762f95c..712462fbb 100644 --- a/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 +++ b/src/GitHub/private/Auth/DeviceFlow/Invoke-GitHubDeviceFlowLogin.ps1 @@ -33,7 +33,7 @@ # The refresh token to use for re-authentication. [Parameter()] - [string] $RefreshToken + [securestring] $RefreshToken ) do { diff --git a/src/GitHub/private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1 b/src/GitHub/private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1 index fda7406cb..171d5bbe1 100644 --- a/src/GitHub/private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1 +++ b/src/GitHub/private/Auth/DeviceFlow/Request-GitHubAccessToken.ps1 @@ -35,7 +35,7 @@ Mandatory, ParameterSetName = 'RefreshToken' )] - [string] $RefreshToken + [securestring] $RefreshToken ) $body = @{ @@ -44,7 +44,7 @@ if ($PSBoundParameters.ContainsKey('RefreshToken')) { $body += @{ - 'refresh_token' = $RefreshToken + 'refresh_token' = (ConvertFrom-SecureString $RefreshToken -AsPlainText) 'grant_type' = 'refresh_token' } } @@ -67,6 +67,8 @@ Write-Verbose ($RESTParams.GetEnumerator() | Out-String) $tokenResponse = Invoke-RestMethod @RESTParams -Verbose:$false + + Write-Verbose ($tokenResponse | ConvertTo-Json | Out-String) return $tokenResponse } catch { Write-Error $_ diff --git a/src/GitHub/private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1 b/src/GitHub/private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1 index bdc393b51..dc6cdf796 100644 --- a/src/GitHub/private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1 +++ b/src/GitHub/private/Auth/DeviceFlow/Request-GitHubDeviceCode.ps1 @@ -56,4 +56,3 @@ throw $_ } } - diff --git a/src/GitHub/private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1 b/src/GitHub/private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1 index cc1e0411d..867d5890e 100644 --- a/src/GitHub/private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1 +++ b/src/GitHub/private/Auth/DeviceFlow/Wait-GitHubAccessToken.ps1 @@ -38,7 +38,7 @@ Mandatory, ParameterSetName = 'RefreshToken' )] - [string] $RefreshToken, + [securestring] $RefreshToken, # The interval to wait between polling for the token. [Parameter()] diff --git a/src/GitHub/private/Config/Config.ps1 b/src/GitHub/private/Config/Config.ps1 deleted file mode 100644 index de2131326..000000000 --- a/src/GitHub/private/Config/Config.ps1 +++ /dev/null @@ -1,28 +0,0 @@ -$script:ConfigTemplate = [pscustomobject]@{ # $script:ConfigTemplate - App = [pscustomobject]@{ # $script:ConfigTemplate.App - API = [pscustomobject]@{ # $script:ConfigTemplate.App.API - BaseURI = 'https://api.github.com' # $script:ConfigTemplate.App.API.BaseURI - Version = '2022-11-28' # $script:ConfigTemplate.App.API.Version - } - Defaults = [pscustomobject]@{} # $script:ConfigTemplate.App.Defaults - } - User = [pscustomobject]@{ # $script:ConfigTemplate.User - Auth = [pscustomobject]@{ # $script:ConfigTemplate.User.Auth - AccessToken = [pscustomobject]@{ # $script:ConfigTemplate.User.Auth.AccessToken - Value = '' # $script:ConfigTemplate.User.Auth.AccessToken.Value - ExpirationDate = [datetime]::MinValue # $script:ConfigTemplate.User.Auth.AccessToken.ExpirationDate - } - ClientID = '' # $script:ConfigTemplate.User.Auth.ClientID - Mode = '' # $script:ConfigTemplate.User.Auth.Mode - RefreshToken = [pscustomobject]@{ - Value = '' # $script:ConfigTemplate.User.Auth.RefreshToken.Value - ExpirationDate = [datetime]::MinValue # $script:ConfigTemplate.User.Auth.RefreshToken.ExpirationDate - } - Scope = '' # $script:ConfigTemplate.User.Auth.Scope - } - Defaults = [pscustomobject]@{ # $script:ConfigTemplate.User.Defaults - Owner = '' # $script:ConfigTemplate.User.Defaults.Owner - Repo = '' # $script:ConfigTemplate.User.Defaults.Repo - } - } -} diff --git a/src/GitHub/private/Config/Initialize-SecretVault.ps1 b/src/GitHub/private/Config/Initialize-SecretVault.ps1 index 05b619d5c..b17dee6f6 100644 --- a/src/GitHub/private/Config/Initialize-SecretVault.ps1 +++ b/src/GitHub/private/Config/Initialize-SecretVault.ps1 @@ -16,26 +16,27 @@ function Initialize-SecretVault { Initializes a secret vault named 'SecretStore' using the 'Microsoft.PowerShell.SecretStore' module. .NOTES - For more information aobut secret vaults, see https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules + For more information about secret vaults, see https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/overview?view=ps-modules #> + [OutputType([void])] [CmdletBinding()] param ( # The name of the secret vault. [Parameter()] - [string] $Name, + [string] $Name = 'SecretStore', # The type of the secret vault. [Parameter()] [Alias('ModuleName')] - [string] $Type + [string] $Type = 'Microsoft.PowerShell.SecretStore' ) - $secretVault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type } - $secretVaultExists = $secretVault.count -ne 0 - Write-Verbose "[$Name] - exists - [$secretVaultExists]" - if (-not $secretVaultExists) { - Write-Verbose "[$Name] - Registering" + $functionName = $MyInvocation.MyCommand.Name + + $vault = Get-SecretVault | Where-Object { $_.ModuleName -eq $Type } + if (-not $vault) { + Write-Verbose "[$functionName] - [$Type] - Registering" switch ($Type) { 'Microsoft.PowerShell.SecretStore' { @@ -51,11 +52,14 @@ function Initialize-SecretVault { Reset-SecretStore @vaultParameters } } + Write-Verbose "[$functionName] - [$Type] - Done" + } else { + Write-Verbose "[$functionName] - [$Type] - already registered" } $secretStore = Get-SecretVault | Where-Object { $_.Name -eq $Name } - $secretStoreExists = $secretStore.count -ne 0 - if (-not $secretStoreExists) { + if (-not $secretStore) { + Write-Verbose "[$functionName] - [$Name] - Registering" $secretVault = @{ Name = $Name ModuleName = $Type @@ -63,5 +67,8 @@ function Initialize-SecretVault { Description = 'SecretStore' } Register-SecretVault @secretVault + Write-Verbose "[$functionName] - [$Name] - Done" + } else { + Write-Verbose "[$functionName] - [$Name] - already registered" } } diff --git a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 new file mode 100644 index 000000000..54f0933bc --- /dev/null +++ b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 @@ -0,0 +1,62 @@ +function Reset-GitHubConfig { + <# + .SYNOPSIS + Reset the GitHub configuration. + + .DESCRIPTION + Reset the GitHub configuration. Specific scopes can be reset by using the Scope parameter. + + .EXAMPLE + Reset-GitHubConfig + + Resets the entire GitHub configuration. + + .EXAMPLE + Reset-GitHubConfig -Scope 'Auth' + + Resets the Auth related variables of the GitHub configuration. + #> + [Alias('Reset-GHConfig')] + [OutputType([void])] + [CmdletBinding()] + param( + # Reset the GitHub configuration for a specific scope. + [Parameter()] + [ValidateSet('Auth', 'All')] + [string] $Scope = 'All' + ) + + Write-Verbose "Resetting GitHub configuration for scope '$Scope'..." + switch ($Scope) { + 'Auth' { + $Settings = @{ + AccessToken = [securestring]::new() + AccessTokenExpirationDate = [datetime]::MinValue + AccessTokenType = '' + AuthType = '' + DeviceFlowType = '' + RefreshToken = [securestring]::new() + RefreshTokenExpirationDate = [datetime]::MinValue + Scope = '' + } + } + 'All' { + $Settings = @{ + AccessToken = [securestring]::new() + AccessTokenExpirationDate = [datetime]::MinValue + AccessTokenType = '' + ApiBaseUri = 'https://api.github.com' + ApiVersion = '2022-11-28' + AuthType = '' + DeviceFlowType = '' + Owner = '' + RefreshToken = [securestring]::new() + RefreshTokenExpirationDate = [datetime]::MinValue + Repo = '' + Scope = '' + UserName = '' + } + } + } + Set-GitHubConfig @Settings +} diff --git a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 new file mode 100644 index 000000000..4dbc66c65 --- /dev/null +++ b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 @@ -0,0 +1,111 @@ +function Invoke-GitHubAPI { + <# + .SYNOPSIS + Calls the GitHub API using the provided parameters. + + .DESCRIPTION + This function is a wrapper around Invoke-RestMethod tailored for calling GitHub's API. + It automatically handles the endpoint URI construction, headers, and token authentication. + + .EXAMPLE + Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET + + Gets all open pull requests for the specified repository. + + .EXAMPLE + Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' } + + Gets all open pull requests for the specified repository, filtered by the 'state' parameter. + + .EXAMPLE + Invoke-GitHubAPI -ApiEndpoint '/repos/user/repo/pulls' -Method GET -Body @{ state = 'open' } -Accept 'application/vnd.github.v3+json' + + Gets all open pull requests for the specified repository, filtered by the 'state' parameter, and using the specified 'Accept' header. +#> + [CmdletBinding()] + param ( + # The HTTP method to be used for the API request. It can be one of the following: GET, POST, PUT, DELETE, or PATCH. + [Parameter()] + [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = 'GET', + + # The base URI for the GitHub API. This is usually 'https://api.github.com', but can be adjusted if necessary. + [Parameter()] + [string] $ApiBaseUri = (Get-GitHubConfig -Name ApiBaseUri -AsPlainText), + + # The specific endpoint for the API call, e.g., '/repos/user/repo/pulls'. + [Parameter(Mandatory)] + [string] $ApiEndpoint, + + # The body of the API request. This can be a hashtable or a string. If a hashtable is provided, it will be converted to JSON. + [Parameter()] + [Object] $Body, + + # The 'Accept' header for the API request. If not provided, the default will be used by GitHub's API. + [Parameter()] + [string] $Accept, + + # Specifies the HTTP version used for the request. + [Parameter()] + $HttpVersion = '2.0', + + # Support Pagination Relation Links per RFC5988. + [Parameter()] + $FollowRelLink = $true, + + # The secure token used for authentication in the GitHub API. It should be stored as a SecureString to ensure it's kept safe in memory. + [Parameter()] + [SecureString] $AccessToken = (Get-GitHubConfig -Name AccessToken), + + # The 'Content-Type' header for the API request. The default is 'application/vnd.github+json'. + [Parameter()] + [string] $ContentType = 'application/vnd.github+json', + + # The GitHub API version to be used. By default, it pulls from a configuration script variable. + [Parameter()] + [string] $Version = (Get-GitHubConfig -Name ApiVersion -AsPlainText) + ) + + $functionName = $MyInvocation.MyCommand.Name + + $headers = @{ + Accept = $Accept + 'X-GitHub-Api-Version' = $Version + } + + ($headers.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { $headers.Remove($_.Name) } + + $URI = ("$ApiBaseUri/" -replace '/$', '') + ("/$ApiEndpoint" -replace '^/', '') + + $APICall = @{ + Uri = $URI + Method = $Method + Headers = $Headers + Authentication = 'Bearer' + Token = $AccessToken + ContentType = $ContentType + HttpVersion = $HttpVersion + FollowRelLink = $FollowRelLink + StatusCodeVariable = 'StatusCode' + ResponseHeadersVariable = 'ResponseHeaders' + } + + if ($Body) { + if ($Body -is [string]) { + $APICall.Body = $Body + } else { + $APICall.Body = $Body | ConvertTo-Json -Depth 100 + } + } + + try { + Invoke-RestMethod @APICall | Write-Output + Write-Verbose ($StatusCode | ConvertTo-Json -Depth 100) + Write-Verbose ($ResponseHeaders | ConvertTo-Json -Depth 100) + } catch [System.Net.WebException] { + Write-Error "[$functionName] - WebException - $($_.Exception.Message)" + throw $_ + } catch { + Write-Error "[$functionName] - GeneralException - $($_.Exception.Message)" + throw $_ + } +} diff --git a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 index af7999361..da99ded35 100644 --- a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 +++ b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 @@ -16,16 +16,14 @@ Connect-GitHubAccount Connects to GitHub using a device flow login. + If the user has already logged in, the access token will be refreshed. .EXAMPLE - Connect-GitHubAccount -AccessToken 'ghp_####' + Connect-GitHubAccount -AccessToken + ! Enter your personal access token: ************* - Connects to GitHub using a personal access token (PAT). - - .EXAMPLE - Connect-GitHubAccount -Refresh - - Refreshes the access token. + User gets prompted for the access token and stores it in the secret store. + The token is used when connecting to GitHub. .EXAMPLE Connect-GitHubAccount -Mode 'OAuthApp' -Scope 'gist read:org repo workflow' @@ -57,72 +55,121 @@ # For more information on scopes visit: # https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps [Parameter(ParameterSetName = 'DeviceFlow')] - [string] $Scope, - - # Refresh the access token. - [Parameter( - Mandatory, - ParameterSetName = 'Refresh' - )] - [switch] $Refresh, + [string] $Scope = 'gist read:org repo workflow', # The personal access token to use for authentication. [Parameter( Mandatory, ParameterSetName = 'PAT' )] - [String] $AccessToken + [switch] $AccessToken ) - $vault = Get-SecretVault | Where-Object -Property ModuleName -EQ $script:SecretVault.Type - - if ($null -eq $vault) { - Initialize-SecretVault -Name $script:SecretVault.Name -Type $script:SecretVault.Type - $vault = Get-SecretVault | Where-Object -Property ModuleName -EQ $script:SecretVault.Type - } - - $clientID = $script:Auth.$Mode.ClientID + $envVar = Get-ChildItem -Path 'Env:' | Where-Object Name -In 'GH_TOKEN', 'GITHUB_TOKEN' | Select-Object -First 1 + $envVarPresent = $envVar.count -gt 0 + $AuthType = $envVarPresent ? 'sPAT' : $PSCmdlet.ParameterSetName - switch ($PSCmdlet.ParameterSetName) { - 'Refresh' { - Write-Verbose 'Refreshing access token...' - $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken $script:Config.User.Auth.RefreshToken.Value - } + switch ($AuthType) { 'DeviceFlow' { Write-Verbose 'Logging in using device flow...' - if ([string]::IsNullOrEmpty($Scope) -and ($Mode -eq 'OAuthApp')) { - $Scope = 'gist read:org repo workflow' - } - if ($script:Config.PSObject.Properties.Name -contains 'App') { - Reset-GitHubConfig -Scope 'User.Auth' + $clientID = $script:Auth.$Mode.ClientID + if ($Mode -ne (Get-GitHubConfig -Name DeviceFlowType -AsPlainText -ea SilentlyContinue)) { + Write-Verbose "Using $Mode authentication..." + $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope } else { - Reset-GitHubConfig -Scope 'All' + $accessTokenValidity = [datetime](Get-GitHubConfig -Name 'AccessTokenExpirationDate' -AsPlainText) - (Get-Date) + $accessTokenIsValid = $accessTokenValidity.Seconds -gt 0 + $accessTokenValidityText = "$($accessTokenValidity.Hours):$($accessTokenValidity.Minutes):$($accessTokenValidity.Seconds)" + if ($accessTokenIsValid) { + if ($accessTokenValidity -gt 4) { + Write-Host '✓ ' -ForegroundColor Green -NoNewline + Write-Host "Access token is still valid for $accessTokenValidityText ..." + return + } else { + Write-Host '⚠ ' -ForegroundColor Yellow -NoNewline + Write-Host "Access token remaining validity $accessTokenValidityText. Refreshing access token..." + $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken) + } + } else { + $refreshTokenValidity = [datetime](Get-GitHubConfig -Name 'RefreshTokenExpirationDate' -AsPlainText) - (Get-Date) + $refreshTokenIsValid = $refreshTokenValidity.Seconds -gt 0 + if ($refreshTokenIsValid) { + Write-Host '⚠ ' -ForegroundColor Yellow -NoNewline + Write-Verbose 'Access token expired. Refreshing access token...' + $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken) + } else { + Write-Verbose "Using $Mode authentication..." + $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope + } + } + } + Reset-GitHubConfig -Scope 'Auth' + switch ($Mode) { + 'GitHubApp' { + $settings = @{ + AccessToken = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token + AccessTokenExpirationDate = (Get-Date).AddSeconds($tokenResponse.expires_in) + AccessTokenType = $tokenResponse.access_token -replace '_.*$', '_*' + ApiBaseUri = 'https://api.github.com' + ApiVersion = '2022-11-28' + AuthType = $AuthType + DeviceFlowType = $Mode + RefreshToken = ConvertTo-SecureString -AsPlainText $tokenResponse.refresh_token + RefreshTokenExpirationDate = (Get-Date).AddSeconds($tokenResponse.refresh_token_expires_in) + Scope = $tokenResponse.scope + } + } + 'OAuthApp' { + $settings = @{ + AccessToken = ConvertTo-SecureString -AsPlainText $tokenResponse.access_token + AccessTokenType = $tokenResponse.access_token -replace '_.*$', '_*' + ApiBaseUri = 'https://api.github.com' + ApiVersion = '2022-11-28' + AuthType = $AuthType + DeviceFlowType = $Mode + Scope = $tokenResponse.scope + } + } } - $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope - $script:Config.User.Auth.Mode = $Mode - $script:Config.User.Auth.ClientID = $clientID + Set-GitHubConfig @settings + break } 'PAT' { Write-Verbose 'Logging in using personal access token...' - Reset-GitHubConfig -Scope 'User.Auth' - $script:Config.User.Auth.AccessToken.Value = $Token - $script:Config.User.Auth.Mode = 'PAT' - Save-GitHubConfig - Write-Host '✓ ' -ForegroundColor Green -NoNewline - Write-Host 'Logged in using a personal access token (PAT)!' - return + Reset-GitHubConfig -Scope 'Auth' + Write-Host '! ' -ForegroundColor DarkYellow -NoNewline + Start-Process 'https://github.com/settings/tokens' + $accessTokenValue = Read-Host -Prompt 'Enter your personal access token' -AsSecureString + $prefix = (ConvertFrom-SecureString $accessTokenValue -AsPlainText) -replace '_.*$', '_*' + if ($prefix -notmatch '^ghp_|^github_pat_') { + Write-Host '⚠ ' -ForegroundColor Yellow -NoNewline + Write-Host "Unexpected access token format: $prefix" + } + $settings = @{ + AccessToken = $accessTokenValue + AccessTokenType = $prefix + ApiBaseUri = 'https://api.github.com' + ApiVersion = '2022-11-28' + AuthType = $AuthType + } + Set-GitHubConfig @settings + break + } + 'sPAT' { + Write-Verbose 'Logging in using system access token...' + Reset-GitHubConfig -Scope 'Auth' + $prefix = $envVar.Value -replace '_.*$', '_*' + $settings = @{ + AccessToken = ConvertTo-SecureString -AsPlainText $envVar.Value + AccessTokenType = $prefix + ApiBaseUri = 'https://api.github.com' + ApiVersion = '2022-11-28' + AuthType = 'sPAT' + } + Set-GitHubConfig @settings } } - if ($tokenResponse) { - $script:Config.User.Auth.AccessToken.Value = $tokenResponse.access_token - $script:Config.User.Auth.AccessToken.ExpirationDate = (Get-Date).AddSeconds($tokenResponse.expires_in) - $script:Config.User.Auth.RefreshToken.Value = $tokenResponse.refresh_token - $script:Config.User.Auth.RefreshToken.ExpirationDate = (Get-Date).AddSeconds($tokenResponse.refresh_token_expires_in) - $script:Config.User.Auth.Scope = $tokenResponse.scope - } - - Save-GitHubConfig Write-Host '✓ ' -ForegroundColor Green -NoNewline Write-Host 'Logged in to GitHub!' } diff --git a/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 b/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 index 6df6137a1..754786541 100644 --- a/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 +++ b/src/GitHub/public/Auth/Disconnect-GitHubAccount.ps1 @@ -26,8 +26,8 @@ [CmdletBinding()] param () - Reset-GitHubConfig + Reset-GitHubConfig -Scope 'All' - Write-Host "✓ " -ForegroundColor Green -NoNewline - Write-Host "Logged out of GitHub!" + Write-Host '✓ ' -ForegroundColor Green -NoNewline + Write-Host 'Logged out of GitHub!' } diff --git a/src/GitHub/public/Config/Get-GitHubConfig.ps1 b/src/GitHub/public/Config/Get-GitHubConfig.ps1 index 8f2ff66ba..8de2774f3 100644 --- a/src/GitHub/public/Config/Get-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Get-GitHubConfig.ps1 @@ -5,30 +5,29 @@ .DESCRIPTION Get the current GitHub configuration. - If the Refresh switch is used, the configuration will be refreshed from the configuration file. + The configuration is first loaded from the configuration file. .EXAMPLE Get-GitHubConfig Returns the current GitHub configuration. - .EXAMPLE - Get-GitHubConfig -Refresh - - Refreshes the current GitHub configuration from the configuration store beofre returning it. #> [Alias('Get-GHConfig')] - [OutputType([PSCustomObject])] + [Alias('GGHC')] + [OutputType([object])] [CmdletBinding()] param ( - # Refresh the configuration from the configuration store before returning it. - [Parameter()] - [switch] $Refresh + [string] $Name, + [switch] $AsPlainText ) - - if ($Refresh) { - Restore-GitHubConfig + $prefix = $script:SecretVault.Prefix + if ($Name) { + $Name = "$prefix$Name" + Get-Secret -Name $Name -Vault $script:SecretVault.Name -AsPlainText:$AsPlainText + } else { + Get-SecretInfo | Where-Object Name -like "$prefix*" | ForEach-Object { + Get-Secret -Name $_.Name -Vault $script:SecretVault.Name -AsPlainText:$AsPlainText + } } - - $script:Config } diff --git a/src/GitHub/public/Config/Reset-GitHubConfig.ps1 b/src/GitHub/public/Config/Reset-GitHubConfig.ps1 deleted file mode 100644 index 42e5994ad..000000000 --- a/src/GitHub/public/Config/Reset-GitHubConfig.ps1 +++ /dev/null @@ -1,55 +0,0 @@ -function Reset-GitHubConfig { - <# - .SYNOPSIS - Reset the GitHub configuration. - - .DESCRIPTION - Reset the GitHub configuration. Specific scopes can be reset by using the Scope parameter. - - .EXAMPLE - Reset-GitHubConfig - - Resets the entire GitHub configuration. - - .EXAMPLE - Reset-GitHubConfig -Scope 'App.API' - - Resets the App.API scope of the GitHub configuration. - #> - [Alias('Reset-GHConfig')] - [OutputType([void])] - [CmdletBinding()] - param( - # Reset the GitHub configuration for a specific scope. - [Parameter()] - [ValidateSet('App', 'App.API', 'App.Defaults', 'User', 'User.Auth', 'User.Defaults', 'All')] - [string] $Scope = 'All' - ) - - Write-Verbose "Resetting GitHub configuration for scope '$Scope'..." - switch ($Scope) { - 'App' { - $script:Config.App = $script:ConfigTemplate.App | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - 'App.API' { - $script:Config.App.API = $script:ConfigTemplate.App.API | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - 'App.Defaults' { - $script:Config.App.Defaults = $script:ConfigTemplate.App.Defaults | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - 'User' { - $script:Config.User = $script:ConfigTemplate.User | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - 'User.Auth' { - $script:Config.User.Auth = $script:ConfigTemplate.User.Auth | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - 'User.Defaults' { - $script:Config.User.Defaults = $script:ConfigTemplate.User.Defaults | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - 'All' { - $script:Config = $script:ConfigTemplate | ConvertTo-Json -Depth 100 | ConvertFrom-Json - } - } - - Save-GitHubConfig -} diff --git a/src/GitHub/public/Config/Restore-GitHubConfig.ps1 b/src/GitHub/public/Config/Restore-GitHubConfig.ps1 deleted file mode 100644 index 48ed8d390..000000000 --- a/src/GitHub/public/Config/Restore-GitHubConfig.ps1 +++ /dev/null @@ -1,38 +0,0 @@ -#Requires -Version 7.0 -#Requires -Modules Microsoft.PowerShell.SecretManagement - -function Restore-GitHubConfig { - <# - .SYNOPSIS - Restore the GitHub configuration from the configuration store. - - .DESCRIPTION - Restore the GitHub configuration from the configuration store. - - .EXAMPLE - Restore-GitHubConfig - - Restores the GitHub configuration from the configuration store. - #> - [Alias('Load-GitHubConfig')] - [Alias('Load-GHConfig')] - [Alias('Restore-GHConfig')] - [OutputType([void])] - [CmdletBinding()] - param() - - $vault = Get-SecretVault -Name $script:SecretVault.Name - $vaultExists = $vault.count -eq 1 - if ($vaultExists) { - $secretExists = Get-SecretInfo -Name $script:SecretVault.Secret.Name -Vault $script:SecretVault.Name - if ($secretExists) { - $script:Config = Get-Secret -Name $script:SecretVault.Secret.Name -AsPlainText -Vault $script:SecretVault.Name | ConvertFrom-Json - } else { - Write-Verbose "Unable to restore configuration." - Write-Verbose "The secret [$($script:SecretVault.Secret.Name)] does not exist in the vault [$($script:SecretVault.Name)]." - } - } else { - Write-Verbose "Unable to restore configuration." - Write-Verbose "The vault [$($script:SecretVault.Name)] does not exist." - } -} diff --git a/src/GitHub/public/Config/Save-GitHubConfig.ps1 b/src/GitHub/public/Config/Save-GitHubConfig.ps1 deleted file mode 100644 index 76a861eb7..000000000 --- a/src/GitHub/public/Config/Save-GitHubConfig.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -#Requires -Version 7.0 -#Requires -Modules Microsoft.PowerShell.SecretManagement - -function Save-GitHubConfig { - <# - .SYNOPSIS - Save the GitHub configuration to the configuration store. - - .DESCRIPTION - Save the GitHub configuration to the configuration store. - - .EXAMPLE - Save-GitHubConfig - - Saves the GitHub configuration to the configuration store. - #> - [Alias('Save-GHConfig')] - [OutputType([void])] - [CmdletBinding()] - param() - - $configJson = $script:Config | ConvertTo-Json -Depth 100 - Set-Secret -Name $script:SecretVault.Secret.Name -Secret $configJson -Vault $script:SecretVault.Name -} diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index 8b85baf7a..dd128166a 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -7,43 +7,127 @@ Set the GitHub configuration. Specific scopes can be set by using the parameters. .EXAMPLE - Set-GitHubConfig -APIBaseURI 'https://api.github.com' -APIVersion '2022-11-28' + Set-GitHubConfig -APIBaseURI 'https://api.github.com" -APIVersion '2022-11-28' Sets the App.API scope of the GitHub configuration. + + .EXAMPLE + Set-GitHubConfig -Name "MyFavouriteRepo" -Value 'https://github.com/PSModule/GitHub' + + Sets a item called 'MyFavouriteRepo' in the GitHub configuration. #> [Alias('Set-GHConfig')] [CmdletBinding()] param ( + # Set the access token type. + [Parameter()] + [string] $AccessTokenType = '', + + # Set the access token. + [Parameter()] + [securestring] $AccessToken = '', + + # Set the access token expiration date. + [Parameter()] + [datetime] $AccessTokenExpirationDate, + # Set the API Base URI. [Parameter()] - [string] $APIBaseURI, + [string] $ApiBaseUri, # Set the GitHub API Version. [Parameter()] - [string] $APIVersion, + [string] $ApiVersion, + + # Set the authentication type. + [Parameter()] + [string] $AuthType, + + # Set the device flow type. + [Parameter()] + [string] $DeviceFlowType, # Set the default for the Owner parameter. [Parameter()] [string] $Owner, + # Set the refresh token. + [Parameter()] + [securestring] $RefreshToken, + + # Set the refresh token expiration date. + [Parameter()] + [datetime] $RefreshTokenExpirationDate, + # Set the default for the Repo parameter. [Parameter()] - [string] $Repo + [string] $Repo, + + # Set the scope. + [Parameter()] + [string] $Scope, + + # Set the GitHub username. + [Parameter()] + [string] $UserName, + + # Choose a custom name to set. + [Parameter()] + [string] $Name, + + # Choose a custom value to set. + [Parameter()] + [string] $Value = '' ) + $prefix = $script:SecretVault.Prefix + + #All timestamps return in UTC time, ISO 8601 format: YYYY-MM-DDTHH:MM:SSZ + #Also: use Set-Secret -NAme ... -Value ... -Metadata @{Type = 'DateTime'} to set a datetime value + # https://learn.microsoft.com/en-us/powershell/utility-modules/secretmanagement/how-to/manage-secretstore?view=ps-modules#adding-metadata + switch ($PSBoundParameters.Keys) { - 'APIBaseURI' { - $script:Config.App.API.BaseURI = $APIBaseURI + 'AccessToken' { + Set-Secret -Name "$prefix`AccessToken" -SecureStringSecret $AccessToken -Vault $script:SecretVault.Name + } + 'AccessTokenExpirationDate' { + Set-Secret -Name "$prefix`AccessTokenExpirationDate" -Secret $AccessTokenExpirationDate.ToString() -Vault $script:SecretVault.Name } - 'APIVersion' { - $script:Config.App.API.Version = $APIVersion + 'AccessTokenType' { + Set-Secret -Name "$prefix`AccessTokenType" -Secret $AccessTokenType -Vault $script:SecretVault.Name + } + 'ApiBaseUri' { + Set-Secret -Name "$prefix`ApiBaseUri" -Secret $ApiBaseUri -Vault $script:SecretVault.Name + } + 'ApiVersion' { + Set-Secret -Name "$prefix`ApiVersion" -Secret $ApiVersion -Vault $script:SecretVault.Name + } + 'AuthType' { + Set-Secret -Name "$prefix`AuthType" -Secret $AuthType -Vault $script:SecretVault.Name + } + 'DeviceFlowType' { + Set-Secret -Name "$prefix`DeviceFlowType" -Secret $DeviceFlowType -Vault $script:SecretVault.Name } 'Owner' { - $script:Config.User.Defaults.Owner = $Owner + Set-Secret -Name "$prefix`Owner" -Secret $Owner -Vault $script:SecretVault.Name + } + 'RefreshToken' { + Set-Secret -Name "$prefix`RefreshToken" -SecureStringSecret $RefreshToken -Vault $script:SecretVault.Name + } + 'RefreshTokenExpirationDate' { + Set-Secret -Name "$prefix`RefreshTokenExpirationDate" -Secret $RefreshTokenExpirationDate.ToString() -Vault $script:SecretVault.Name } 'Repo' { - $script:Config.User.Defaults.Repo = $Repo + Set-Secret -Name "$prefix`Repo" -Secret $Repo -Vault $script:SecretVault.Name + } + 'Scope' { + Set-Secret -Name "$prefix`Scope" -Secret $Scope -Vault $script:SecretVault.Name + } + 'UserName' { + Set-Secret -Name "$prefix`UserName" -Secret $UserName -Vault $script:SecretVault.Name + } + 'Name' { + Set-Secret -Name "$prefix$Name" -Secret $Value -Vault $script:SecretVault.Name } } - Save-GitHubConfig } diff --git a/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 b/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 new file mode 100644 index 000000000..ed1443291 --- /dev/null +++ b/src/GitHub/public/Meta/Get-GitHubApiVersions.ps1 @@ -0,0 +1,29 @@ +function Get-GitHubApiVersions { + <# + .SYNOPSIS + Get all API versions. + + .DESCRIPTION + Get all supported GitHub API versions. + + .EXAMPLE + Get-GitHubApiVersions + + Get all supported GitHub API versions. + + .NOTES + https://docs.github.com/rest/meta/meta#get-all-api-versions + #> + [OutputType([string[]])] + [CmdletBinding()] + param () + + $inputObject = @{ + ApiEndpoint = '/versions' + Method = 'GET' + } + + $response = Invoke-GitHubAPI @inputObject + + $response +} diff --git a/src/GitHub/public/Meta/Get-GitHubMeta.ps1 b/src/GitHub/public/Meta/Get-GitHubMeta.ps1 new file mode 100644 index 000000000..cae684cf8 --- /dev/null +++ b/src/GitHub/public/Meta/Get-GitHubMeta.ps1 @@ -0,0 +1,35 @@ +function Get-GitHubMeta { + <# + .SYNOPSIS + Get GitHub meta information. + + .DESCRIPTION + Returns meta information about GitHub, including a list of GitHub's IP addresses. For more information, see "[About GitHub's IP addresses](https://docs.github.com/articles/about-github-s-ip-addresses/)." + + The API's response also includes a list of GitHub's domain names. + + The values shown in the documentation's response are example values. You must always query the API directly to get the latest values. + + **Note:** This endpoint returns both IPv4 and IPv6 addresses. However, not all features support IPv6. You should refer to the specific documentation for each feature to determine if IPv6 is supported. + + .EXAMPLE + Get-GitHubMeta + + Returns meta information about GitHub, including a list of GitHub's IP addresses. + + .NOTES + https://docs.github.com/rest/meta/meta#get-apiname-meta-information + #> + [OutputType([object])] + [CmdletBinding()] + param () + + $inputObject = @{ + ApiEndpoint = '/meta' + Method = 'GET' + } + + $response = Invoke-GitHubAPI @inputObject + + $response +} diff --git a/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 b/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 new file mode 100644 index 000000000..946bfe86c --- /dev/null +++ b/src/GitHub/public/Meta/Get-GitHubOctocat.ps1 @@ -0,0 +1,49 @@ +function Get-GitHubOctocat { + <# + .SYNOPSIS + Get Octocat. + + .DESCRIPTION + Get the octocat as ASCII art. + + .EXAMPLE + Get-GitHubOctocat + + Get the octocat as ASCII art + + .EXAMPLE + Get-GitHubOctocat -S 'The glass is never half empty. It's just twice as big as it needs to be.' + + Get the octocat as ASCII art with a custom saying + + .NOTES + https://docs.github.com/rest/meta/meta#get-octocat + #> + [OutputType([string])] + [CmdletBinding()] + param ( + # The words to show in Octocat's speech bubble + [Parameter()] + [Alias('Say')] + [Alias('Saying')] + [string] + $S = "The glass is never half empty. Its just twice as big as it needs to be." + ) + + # $query = [System.Web.HttpUtility]::UrlEncode($S) + # $query = [System.Uri]::EscapeDataString($S) + + $body = @{ + s = $S + } + + $inputObject = @{ + APIEndpoint = "/octocat" + Method = 'GET' + Body = $body + } + + $response = Invoke-GitHubAPI @inputObject + + $response +} diff --git a/src/GitHub/public/Meta/Get-GitHubRoot.ps1 b/src/GitHub/public/Meta/Get-GitHubRoot.ps1 new file mode 100644 index 000000000..a08b507df --- /dev/null +++ b/src/GitHub/public/Meta/Get-GitHubRoot.ps1 @@ -0,0 +1,28 @@ +function Get-GitHubRoot { + <# + .SYNOPSIS + GitHub API Root. + + .DESCRIPTION + Get Hypermedia links to resources accessible in GitHub's REST API. + + .EXAMPLE + Get-GitHubRoot + + Get the root endpoint for the GitHub API. + + .NOTES + https://docs.github.com/rest/meta/meta#github-api-root + #> + [CmdletBinding()] + param () + + $InputObject = @{ + APIEndpoint = '/' + Method = 'GET' + } + + $response = Invoke-GitHubAPI @InputObject + + $response +} diff --git a/src/GitHub/public/Meta/Get-GitHubZen.ps1 b/src/GitHub/public/Meta/Get-GitHubZen.ps1 new file mode 100644 index 000000000..866265a06 --- /dev/null +++ b/src/GitHub/public/Meta/Get-GitHubZen.ps1 @@ -0,0 +1,28 @@ +function Get-GitHubZen { + <# + .SYNOPSIS + Get the Zen of GitHub. + + .DESCRIPTION + Get a random sentence from the Zen of GitHub. + + .EXAMPLE + Get-GitHubZen + + Get a random sentence from the Zen of GitHub. + + .NOTES + https://docs.github.com/rest/meta/meta#get-the-zen-of-github + #> + [CmdletBinding()] + param () + + $InputObject = @{ + APIEndpoint = '/zen' + Method = 'GET' + } + + $Response = Invoke-GitHubAPI @InputObject + + $Response +} diff --git a/tools/utilities/GitHubAPI.ps1 b/tools/utilities/GitHubAPI.ps1 new file mode 100644 index 000000000..9292af143 --- /dev/null +++ b/tools/utilities/GitHubAPI.ps1 @@ -0,0 +1,17 @@ +$APIDocURI = 'https://raw.githubusercontent.com/github/rest-api-description/main' +$Bundled = '/descriptions/api.github.com/api.github.com.json' +$Dereferenced = 'descriptions/api.github.com/dereferenced/api.github.com.deref.json' +$APIDocURI = $APIDocURI + $Bundled +$Response = Invoke-RestMethod -Uri $APIDocURI -Method Get + +# $Response.info # API name = GitHub REST API +# $Response.openapi # Spec version = 3.0.3 +# $Response.servers # API URL = api.github.com +# $Response.externalDocs # API docs URL = docs.github.com/rest +# $Response.components # Type specs +# $Response.paths # API endpoints +# $Response.tags # API categories +# $Response.'x-webhooks' # Webhooks/event docs + + +$Response.paths.'/meta'.get diff --git a/tools/utilities/Local-Testing.ps1 b/tools/utilities/Local-Testing.ps1 index e3b0bb031..ecbe3441c 100644 --- a/tools/utilities/Local-Testing.ps1 +++ b/tools/utilities/Local-Testing.ps1 @@ -4,23 +4,28 @@ Get-Module -Name GitHub -ListAvailable | Uninstall-Module -Force -AllVersions Get-SecretVault | Unregister-SecretVault Get-SecretVault +Get-SecretInfo Get-Module -Name GitHub -ListAvailable -Install-Module -Name GitHub -Verbose -Force -AllowPrerelease - $VerbosePreference = 'Continue' + +Install-Module -Name GitHub -Verbose -Force -AllowPrerelease +$env:PSModulePath += ';C:\Repos\GitHub\PSModule\Modules\GitHub\outputs' Import-Module -Name 'C:\Repos\GitHub\PSModule\Modules\GitHub\src\GitHub\GitHub.psm1' -Verbose -Force Import-Module -Name GitHub -Verbose Clear-Host Get-Command -Module GitHub -Get-Variable | Where-Object -Property Module -ne $null | Select-Object Name, Module, ModuleName +Get-Variable | Where-Object -Property Module -NE $null | Select-Object Name, Module, ModuleName Connect-GitHubAccount -Get-GitHubConfig | ConvertTo-Json -Depth 100 -Get-GitHubConfig -Refresh | ConvertTo-Json -Depth 100 -Restore-GitHubConfig -Verbose -Get-GitHubContext - -Connect-GitHubAccount -Refresh -Verbose - +Connect-GitHubAccount -Mode OAuthApp +Connect-GitHubAccount -AccessToken +Get-GitHubConfig -Name AccessToken -AsPlainText +Get-GitHubConfig -Name AccessTokenExpirationDate -AsPlainText +Get-GitHubConfig -Name RefreshToken -AsPlainText +Get-GitHubConfig -Name RefreshTokenExpirationDate -AsPlainText +Get-GitHubConfig -Name ApiBaseUri -AsPlainText +Invoke-GitHubAPI -Method Get -ApiEndpoint / +Get-GitHubMeta +Get-GitHubOctocat -S 'Hello, World!' Disconnect-GitHubAccount -Verbose -Reset-GitHubConfig -Verbose +$VerbosePreference = 'SIlentlyContinue'