From d014a0e6b054b450c34790ca29f1e8ecc0da88fd Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 21:19:10 +0200 Subject: [PATCH 01/14] Test --- .github/workflows/AutoRest.yml | 39 ++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/AutoRest.yml diff --git a/.github/workflows/AutoRest.yml b/.github/workflows/AutoRest.yml new file mode 100644 index 000000000..8f864c438 --- /dev/null +++ b/.github/workflows/AutoRest.yml @@ -0,0 +1,39 @@ +name: AutoRest - GitHub API + +on: + push: + workflow_dispatch: + +defaults: + run: + shell: pwsh + +jobs: + Build: + name: Build + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Install AutoRest + run: | + npm install -g autorest + npm install -g @autorest/modelerfour + + - name: Download GitHub OpenAPI spec + run: | + curl -L https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json -o api.github.com.json + + - name: Generate PowerShell files + run: | + autorest --input-file=api.github.com.json --output-folder=generated --use=@autorest/modelerfour --powershell + # --powershell.azure-arm --powershell.no-namespace + + - run: | + date > generated.txt + git config user.name github-actions + git config user.email github-actions@github.com + git add . + git commit -m "generated" + git push From 7ea15d0924e056ec961d72a36139706e35fdec59 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 21:21:48 +0200 Subject: [PATCH 02/14] test --- .github/workflows/AutoRest.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/AutoRest.yml b/.github/workflows/AutoRest.yml index 8f864c438..8ba7b1713 100644 --- a/.github/workflows/AutoRest.yml +++ b/.github/workflows/AutoRest.yml @@ -27,8 +27,8 @@ jobs: - name: Generate PowerShell files run: | - autorest --input-file=api.github.com.json --output-folder=generated --use=@autorest/modelerfour --powershell - # --powershell.azure-arm --powershell.no-namespace + autorest --input-file=api.github.com.json --output-folder=generated --powershell + # --powershell.azure-arm --powershell.no-namespace--use=@autorest/modelerfour - run: | date > generated.txt From e2842b04b3533d1820f96a043eddeaecd52f6436 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 21:23:23 +0200 Subject: [PATCH 03/14] fix --- .github/workflows/AutoRest.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/AutoRest.yml b/.github/workflows/AutoRest.yml index 8ba7b1713..d3a1fd2f0 100644 --- a/.github/workflows/AutoRest.yml +++ b/.github/workflows/AutoRest.yml @@ -19,7 +19,6 @@ jobs: - name: Install AutoRest run: | npm install -g autorest - npm install -g @autorest/modelerfour - name: Download GitHub OpenAPI spec run: | @@ -28,7 +27,6 @@ jobs: - name: Generate PowerShell files run: | autorest --input-file=api.github.com.json --output-folder=generated --powershell - # --powershell.azure-arm --powershell.no-namespace--use=@autorest/modelerfour - run: | date > generated.txt From 16df325ba7d5aa15daf2475e0e94d4f8bdc3450a Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 21:24:49 +0200 Subject: [PATCH 04/14] test --- .github/workflows/AutoRest.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/AutoRest.yml b/.github/workflows/AutoRest.yml index d3a1fd2f0..1e5153c82 100644 --- a/.github/workflows/AutoRest.yml +++ b/.github/workflows/AutoRest.yml @@ -26,6 +26,7 @@ jobs: - name: Generate PowerShell files run: | + New-Item -ItemType Directory -Force -Path generated autorest --input-file=api.github.com.json --output-folder=generated --powershell - run: | From 88fef88c27d63eda5a049c412554934452139c74 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 23:16:08 +0200 Subject: [PATCH 05/14] Test with removing empty fields in a api call --- src/GitHub/private/Utilities/Join-Hashtable.ps1 | 12 ++++++++++++ .../Utilities/Remove-EmptyHashTableEntries.ps1 | 9 +++++++++ src/GitHub/public/API/Invoke-GitHubAPI.ps1 | 3 ++- 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/GitHub/private/Utilities/Join-Hashtable.ps1 create mode 100644 src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 diff --git a/src/GitHub/private/Utilities/Join-Hashtable.ps1 b/src/GitHub/private/Utilities/Join-Hashtable.ps1 new file mode 100644 index 000000000..6b79ce58a --- /dev/null +++ b/src/GitHub/private/Utilities/Join-Hashtable.ps1 @@ -0,0 +1,12 @@ +function Join-Hashtable { + [OutputType([void])] + [Alias('Merge-HashTable')] + [CmdletBinding()] + param ( + [hashtable] $Main, + [hashtable] $Overrides + ) + $Overrides.Keys | ForEach-Object { + $Main.$_ = $Overrides.$_ + } +} diff --git a/src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 b/src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 new file mode 100644 index 000000000..7816c3fbc --- /dev/null +++ b/src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 @@ -0,0 +1,9 @@ +function Remove-EmptyHashTableEntries { + [OutputType([void])] + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [hashtable] $Hashtable + ) + ($Hashtable.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { $Hashtable.Remove($_.Name) } +} diff --git a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 index 4dbc66c65..66c1c927e 100644 --- a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 +++ b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 @@ -72,7 +72,7 @@ 'X-GitHub-Api-Version' = $Version } - ($headers.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { $headers.Remove($_.Name) } + Remove-EmptyHashTableEntries -Hashtable $headers $URI = ("$ApiBaseUri/" -replace '/$', '') + ("/$ApiEndpoint" -replace '^/', '') @@ -88,6 +88,7 @@ StatusCodeVariable = 'StatusCode' ResponseHeadersVariable = 'ResponseHeaders' } + Remove-EmptyHashTableEntries -Hashtable $APICall if ($Body) { if ($Body -is [string]) { From 39fcd02f4ab74759881b297c69005f4592dce480 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 23:21:45 +0200 Subject: [PATCH 06/14] remove autoRest collection --- .github/workflows/AutoRest.yml | 38 ---------------------------------- 1 file changed, 38 deletions(-) delete mode 100644 .github/workflows/AutoRest.yml diff --git a/.github/workflows/AutoRest.yml b/.github/workflows/AutoRest.yml deleted file mode 100644 index 1e5153c82..000000000 --- a/.github/workflows/AutoRest.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: AutoRest - GitHub API - -on: - push: - workflow_dispatch: - -defaults: - run: - shell: pwsh - -jobs: - Build: - name: Build - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Install AutoRest - run: | - npm install -g autorest - - - name: Download GitHub OpenAPI spec - run: | - curl -L https://raw.githubusercontent.com/github/rest-api-description/main/descriptions/api.github.com/api.github.com.json -o api.github.com.json - - - name: Generate PowerShell files - run: | - New-Item -ItemType Directory -Force -Path generated - autorest --input-file=api.github.com.json --output-folder=generated --powershell - - - run: | - date > generated.txt - git config user.name github-actions - git config user.email github-actions@github.com - git add . - git commit -m "generated" - git push From 0c1fa76a57ce831ed89effa2222bbf824a016a8e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 23:25:05 +0200 Subject: [PATCH 07/14] Test new Set-GitHubConfig structure --- .../private/Config/Reset-GitHubConfig.ps1 | 2 +- src/GitHub/public/Config/Set-GitHubConfig.ps1 | 111 ++++++++++-------- tools/utilities/Local-Testing.ps1 | 4 +- 3 files changed, 64 insertions(+), 53 deletions(-) diff --git a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 index 54f0933bc..cd69ddce3 100644 --- a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 +++ b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 @@ -58,5 +58,5 @@ } } } - Set-GitHubConfig @Settings + Set-GitHubConfig @Settings -Force } diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index dd128166a..bdd62867b 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -71,63 +71,74 @@ [Parameter()] [string] $UserName, - # Choose a custom name to set. + # Force the setting of the configuration item. [Parameter()] - [string] $Name, - - # Choose a custom value to set. - [Parameter()] - [string] $Value = '' + [switch] $Force ) $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 + #region AccessToken + $accessTokenGetParam = @{ + Name = "$prefix`AccessToken" + Vault = $script:SecretVault.Name + } + $acessTokenSecretInfo = Get-SecretInfo @accessTokenGetParam + $currentAccessTokenMetadata = $acessTokenSecretInfo.Metadata - switch ($PSBoundParameters.Keys) { - '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 - } - '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' { - 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' { - 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 + $accessTokenMetadata = @{} + Join-HashTable -Main $accessTokenMetadata -Overrides $PSBoundParameters + if (-not $Force) { + Remove-EmptyHashTableEntries -Hashtable $accessTokenMetadata + } + + 'AccessToken', 'RefreshToken', 'RefreshTokenExpirationDate', 'Force' | ForEach-Object { + if ($accessTokenMetadata.ContainsKey($_)) { + $accessTokenMetadata.Remove($_) } - 'Name' { - Set-Secret -Name "$prefix$Name" -Secret $Value -Vault $script:SecretVault.Name + } + + Join-HashTable -Main $currentAccessTokenMetadata -Overrides $accessTokenMetadata + + $accessTokenSetParam = @{ + Name = "$prefix`AccessToken" + Vault = $script:SecretVault.Name + SecureStringSecret = $AccessToken + Metadata = $secretInfo.Metadata + } + Remove-EmptyHashTableEntries -Hashtable $accessTokenSetParam + Set-SecretInfo @accessTokenSetParam + #endregion AccessToken + + #region RefreshToken + $refreshTokenGetParam = @{ + Name = "$prefix`RefreshToken" + Vault = $script:SecretVault.Name + } + $acessTokenSecretInfo = Get-SecretInfo @refreshTokenGetParam + $currentRefreshTokenMetadata = $acessTokenSecretInfo.Metadata + + $refreshTokenMetadata = @{} + Join-HashTable -Main $refreshTokenMetadata -Overrides $PSBoundParameters + if (-not $Force) { + Remove-EmptyHashTableEntries -Hashtable $refreshTokenMetadata + } + + 'AccessToken', 'RefreshToken', 'AccessTokenExpirationDate', 'Force' | ForEach-Object { + if ($refreshTokenMetadata.ContainsKey($_)) { + $refreshTokenMetadata.Remove($_) } } + + Join-HashTable -Main $currentRefreshTokenMetadata -DestinationHashTable $refreshTokenMetadata + + $refreshTokenSetParam = @{ + Name = "$prefix`RefreshToken" + Vault = $script:SecretVault.Name + SecureStringSecret = $RefreshToken + Metadata = $secretInfo.Metadata + } + Remove-EmptyHashTableEntries -Hashtable $refreshTokenSetParam + Set-SecretInfo @refreshTokenSetParam + #endregion RefreshToken } diff --git a/tools/utilities/Local-Testing.ps1 b/tools/utilities/Local-Testing.ps1 index ecbe3441c..e42d82ab0 100644 --- a/tools/utilities/Local-Testing.ps1 +++ b/tools/utilities/Local-Testing.ps1 @@ -1,6 +1,6 @@ ##### -Get-Module -Name GitHub -ListAvailable | Remove-Module -Force -Get-Module -Name GitHub -ListAvailable | Uninstall-Module -Force -AllVersions +Get-Module -Name GitHub* -ListAvailable | Remove-Module -Force +Get-Module -Name GitHub* -ListAvailable | Uninstall-Module -Force -AllVersions Get-SecretVault | Unregister-SecretVault Get-SecretVault From cc14baf7100481f92ebceac7a8028fae134da17b Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 23:39:23 +0200 Subject: [PATCH 08/14] Test-New set method --- src/GitHub/public/Config/Set-GitHubConfig.ps1 | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index bdd62867b..b2309630f 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -86,8 +86,12 @@ $acessTokenSecretInfo = Get-SecretInfo @accessTokenGetParam $currentAccessTokenMetadata = $acessTokenSecretInfo.Metadata - $accessTokenMetadata = @{} - Join-HashTable -Main $accessTokenMetadata -Overrides $PSBoundParameters + [hashtable]$accessTokenMetadata = $PSBoundParameters.Keys | ForEach-Object { + @{ + Name = $_ + Value = $PSBoundParameters[$_] + } + } if (-not $Force) { Remove-EmptyHashTableEntries -Hashtable $accessTokenMetadata } @@ -118,8 +122,12 @@ $acessTokenSecretInfo = Get-SecretInfo @refreshTokenGetParam $currentRefreshTokenMetadata = $acessTokenSecretInfo.Metadata - $refreshTokenMetadata = @{} - Join-HashTable -Main $refreshTokenMetadata -Overrides $PSBoundParameters + [hashtable]$refreshTokenMetadata = $PSBoundParameters.Keys | ForEach-Object { + @{ + Name = $_ + Value = $PSBoundParameters[$_] + } + } if (-not $Force) { Remove-EmptyHashTableEntries -Hashtable $refreshTokenMetadata } From 97efcce7bf50131d5ced161ca3f6a126505e1f02 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Tue, 26 Sep 2023 23:43:02 +0200 Subject: [PATCH 09/14] fix set-ghc --- src/GitHub/public/Config/Set-GitHubConfig.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index b2309630f..d6b56a93b 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -119,8 +119,8 @@ Name = "$prefix`RefreshToken" Vault = $script:SecretVault.Name } - $acessTokenSecretInfo = Get-SecretInfo @refreshTokenGetParam - $currentRefreshTokenMetadata = $acessTokenSecretInfo.Metadata + $refreshTokenSecretInfo = Get-SecretInfo @refreshTokenGetParam + $currentRefreshTokenMetadata = $refreshTokenSecretInfo.Metadata [hashtable]$refreshTokenMetadata = $PSBoundParameters.Keys | ForEach-Object { @{ From c4bff4335c9a8471680bc2b06540a9d435c71630 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 27 Sep 2023 18:02:30 +0200 Subject: [PATCH 10/14] Fix auth --- .../Utilities/ConvertFrom-HashTable.ps1 | 11 ++ .../private/Utilities/ConvertTo-HashTable.ps1 | 17 +++ .../private/Utilities/Join-Hashtable.ps1 | 7 +- .../Remove-EmptyHashTableEntries.ps1 | 9 -- .../Utilities/Remove-HashTableEntries.ps1 | 57 +++++++ src/GitHub/public/API/Invoke-GitHubAPI.ps1 | 8 +- .../public/Auth/Connect-GitHubAccount.ps1 | 14 +- src/GitHub/public/Config/Get-GitHubConfig.ps1 | 37 +++-- src/GitHub/public/Config/Set-GitHubConfig.ps1 | 139 ++++++++++-------- tools/utilities/Local-Testing.ps1 | 10 +- 10 files changed, 209 insertions(+), 100 deletions(-) create mode 100644 src/GitHub/private/Utilities/ConvertFrom-HashTable.ps1 create mode 100644 src/GitHub/private/Utilities/ConvertTo-HashTable.ps1 delete mode 100644 src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 create mode 100644 src/GitHub/private/Utilities/Remove-HashTableEntries.ps1 diff --git a/src/GitHub/private/Utilities/ConvertFrom-HashTable.ps1 b/src/GitHub/private/Utilities/ConvertFrom-HashTable.ps1 new file mode 100644 index 000000000..567e8a276 --- /dev/null +++ b/src/GitHub/private/Utilities/ConvertFrom-HashTable.ps1 @@ -0,0 +1,11 @@ +function ConvertFrom-HashTable { + [CmdletBinding()] + param ( + [Parameter( + Mandatory, + ValueFromPipeline + )] + [object]$InputObject + ) + ([pscustomobject](@{} + $InputObject)) +} diff --git a/src/GitHub/private/Utilities/ConvertTo-HashTable.ps1 b/src/GitHub/private/Utilities/ConvertTo-HashTable.ps1 new file mode 100644 index 000000000..c750d5f45 --- /dev/null +++ b/src/GitHub/private/Utilities/ConvertTo-HashTable.ps1 @@ -0,0 +1,17 @@ +function ConvertTo-HashTable { + [CmdletBinding()] + param ( + [Parameter( + Mandatory, + ValueFromPipeline + )] + [pscustomobject]$InputObject + ) + [hashtable]$hashtable = @{} + + foreach ($item in $InputObject.PSobject.Properties) { + Write-Verbose "$($item.Name) : $($item.Value) : $($item.TypeNameOfValue)" + $hashtable.$($item.Name) = $item.Value + } + $hashtable +} diff --git a/src/GitHub/private/Utilities/Join-Hashtable.ps1 b/src/GitHub/private/Utilities/Join-Hashtable.ps1 index 6b79ce58a..b53bedb49 100644 --- a/src/GitHub/private/Utilities/Join-Hashtable.ps1 +++ b/src/GitHub/private/Utilities/Join-Hashtable.ps1 @@ -6,7 +6,12 @@ [hashtable] $Main, [hashtable] $Overrides ) + $hashtable = @{} + $Main.Keys | ForEach-Object { + $hashtable[$_] = $Main[$_] + } $Overrides.Keys | ForEach-Object { - $Main.$_ = $Overrides.$_ + $hashtable[$_] = $Overrides[$_] } + $hashtable } diff --git a/src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 b/src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 deleted file mode 100644 index 7816c3fbc..000000000 --- a/src/GitHub/private/Utilities/Remove-EmptyHashTableEntries.ps1 +++ /dev/null @@ -1,9 +0,0 @@ -function Remove-EmptyHashTableEntries { - [OutputType([void])] - [CmdletBinding()] - param ( - [Parameter(Mandatory)] - [hashtable] $Hashtable - ) - ($Hashtable.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { $Hashtable.Remove($_.Name) } -} diff --git a/src/GitHub/private/Utilities/Remove-HashTableEntries.ps1 b/src/GitHub/private/Utilities/Remove-HashTableEntries.ps1 new file mode 100644 index 000000000..3d7a8c411 --- /dev/null +++ b/src/GitHub/private/Utilities/Remove-HashTableEntries.ps1 @@ -0,0 +1,57 @@ +function Remove-HashtableEntries { + [OutputType([void])] + [CmdletBinding()] + param ( + [Parameter( + Mandatory, + ValueFromPipeline + )] + [hashtable] $Hashtable, + [Parameter()] + [switch] $NullOrEmptyValues, + [Parameter()] + [string[]] $RemoveTypes, + [Parameter()] + [string[]] $RemoveNames, + [Parameter()] + [string[]] $KeepTypes, + [Parameter()] + [string[]] $KeepNames + + ) + if ($NullOrEmptyValues) { + Write-Verbose 'Remove keys with null or empty values' + ($Hashtable.GetEnumerator() | Where-Object { -not $_.Value }) | ForEach-Object { + Write-Verbose " - [$($_.Name)] - Value: [$($_.Value)] - Remove" + $Hashtable.Remove($_.Name) + } + } + if ($RemoveTypes) { + Write-Verbose "Remove keys of type: [$RemoveTypes]" + ($Hashtable.GetEnumerator() | Where-Object { ($_.Value.GetType().Name -in $RemoveTypes) }) | ForEach-Object { + Write-Verbose " - [$($_.Name)] - Type: [$($_.Value.GetType().Name)] - Remove" + $Hashtable.Remove($_.Name) + } + } + if ($KeepTypes) { + Write-Verbose "Remove keys NOT of type: [$KeepTypes]" + ($Hashtable.GetEnumerator() | Where-Object { ($_.Value.GetType().Name -notin $KeepTypes) }) | ForEach-Object { + Write-Verbose " - [$($_.Name)] - Type: [$($_.Value.GetType().Name)] - Remove" + $Hashtable.Remove($_.Name) + } + } + if ($RemoveNames) { + Write-Verbose "Remove keys named: [$RemoveNames]" + ($Hashtable.GetEnumerator() | Where-Object { $_.Name -in $RemoveNames }) | ForEach-Object { + Write-Verbose " - [$($_.Name)] - Remove" + $Hashtable.Remove($_.Name) + } + } + if ($KeepNames) { + Write-Verbose "Remove keys NOT named: [$KeepNames]" + ($Hashtable.GetEnumerator() | Where-Object { $_.Name -notin $KeepNames }) | ForEach-Object { + Write-Verbose " - [$($_.Name)] - Remove" + $Hashtable.Remove($_.Name) + } + } +} diff --git a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 index 66c1c927e..e3ec7793d 100644 --- a/src/GitHub/public/API/Invoke-GitHubAPI.ps1 +++ b/src/GitHub/public/API/Invoke-GitHubAPI.ps1 @@ -30,7 +30,7 @@ # 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), + [string] $ApiBaseUri = (Get-GitHubConfig -Name ApiBaseUri), # The specific endpoint for the API call, e.g., '/repos/user/repo/pulls'. [Parameter(Mandatory)] @@ -62,7 +62,7 @@ # The GitHub API version to be used. By default, it pulls from a configuration script variable. [Parameter()] - [string] $Version = (Get-GitHubConfig -Name ApiVersion -AsPlainText) + [string] $Version = (Get-GitHubConfig -Name ApiVersion) ) $functionName = $MyInvocation.MyCommand.Name @@ -72,7 +72,7 @@ 'X-GitHub-Api-Version' = $Version } - Remove-EmptyHashTableEntries -Hashtable $headers + Remove-HashTableEntries -Hashtable $headers -NullOrEmptyValues $URI = ("$ApiBaseUri/" -replace '/$', '') + ("/$ApiEndpoint" -replace '^/', '') @@ -88,7 +88,7 @@ StatusCodeVariable = 'StatusCode' ResponseHeadersVariable = 'ResponseHeaders' } - Remove-EmptyHashTableEntries -Hashtable $APICall + Remove-HashTableEntries -Hashtable $APICall -NullOrEmptyValues if ($Body) { if ($Body -is [string]) { diff --git a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 index da99ded35..a91cce1e3 100644 --- a/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 +++ b/src/GitHub/public/Auth/Connect-GitHubAccount.ps1 @@ -73,11 +73,11 @@ 'DeviceFlow' { Write-Verbose 'Logging in using device flow...' $clientID = $script:Auth.$Mode.ClientID - if ($Mode -ne (Get-GitHubConfig -Name DeviceFlowType -AsPlainText -ea SilentlyContinue)) { + if ($Mode -ne (Get-GitHubConfig -Name DeviceFlowType -ErrorAction SilentlyContinue)) { Write-Verbose "Using $Mode authentication..." $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -Scope $Scope } else { - $accessTokenValidity = [datetime](Get-GitHubConfig -Name 'AccessTokenExpirationDate' -AsPlainText) - (Get-Date) + $accessTokenValidity = [datetime](Get-GitHubConfig -Name 'AccessTokenExpirationDate') - (Get-Date) $accessTokenIsValid = $accessTokenValidity.Seconds -gt 0 $accessTokenValidityText = "$($accessTokenValidity.Hours):$($accessTokenValidity.Minutes):$($accessTokenValidity.Seconds)" if ($accessTokenIsValid) { @@ -91,7 +91,7 @@ $tokenResponse = Invoke-GitHubDeviceFlowLogin -ClientID $clientID -RefreshToken (Get-GitHubConfig -Name RefreshToken) } } else { - $refreshTokenValidity = [datetime](Get-GitHubConfig -Name 'RefreshTokenExpirationDate' -AsPlainText) - (Get-Date) + $refreshTokenValidity = [datetime](Get-GitHubConfig -Name 'RefreshTokenExpirationDate') - (Get-Date) $refreshTokenIsValid = $refreshTokenValidity.Seconds -gt 0 if ($refreshTokenIsValid) { Write-Host '⚠ ' -ForegroundColor Yellow -NoNewline @@ -140,14 +140,14 @@ 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_') { + $accessTokenType = (ConvertFrom-SecureString $accessTokenValue -AsPlainText) -replace '_.*$', '_*' + if ($accessTokenType -notmatch '^ghp_|^github_pat_') { Write-Host '⚠ ' -ForegroundColor Yellow -NoNewline - Write-Host "Unexpected access token format: $prefix" + Write-Host "Unexpected access token format: $accessTokenType" } $settings = @{ AccessToken = $accessTokenValue - AccessTokenType = $prefix + AccessTokenType = $accessTokenType ApiBaseUri = 'https://api.github.com' ApiVersion = '2022-11-28' AuthType = $AuthType diff --git a/src/GitHub/public/Config/Get-GitHubConfig.ps1 b/src/GitHub/public/Config/Get-GitHubConfig.ps1 index 8de2774f3..556b6ce66 100644 --- a/src/GitHub/public/Config/Get-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Get-GitHubConfig.ps1 @@ -1,33 +1,42 @@ function Get-GitHubConfig { <# .SYNOPSIS - Get the current GitHub configuration. + Get configuration value. .DESCRIPTION - Get the current GitHub configuration. - The configuration is first loaded from the configuration file. + Get a named configuration value from the GitHub configuration file. .EXAMPLE - Get-GitHubConfig - - Returns the current GitHub configuration. + Get-GitHubConfig -Name ApiBaseUri + Get the current GitHub configuration for the ApiBaseUri. #> [Alias('Get-GHConfig')] [Alias('GGHC')] [OutputType([object])] [CmdletBinding()] param ( - [string] $Name, - [switch] $AsPlainText + # Choose a configuration name to get. + [Parameter()] + [string] $Name ) + $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 + $AccessTokenData = Get-SecretInfo -Name "$prefix`RefreshToken" + + switch($Name) { + 'AccessToken' { + Get-Secret -Name "$prefix`AccessToken" + } + 'RefreshToken' { + Get-Secret -Name "$prefix`RefreshToken" + } + 'RefreshTokenExpirationDate' { + $RefreshTokenData = Get-SecretInfo -Name "$prefix`RefreshToken" + $RefreshTokenData.Metadata.$Name + } + default { + $AccessTokenData.Metadata.$Name } } } diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index d6b56a93b..06da4e8ad 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -21,11 +21,11 @@ param ( # Set the access token type. [Parameter()] - [string] $AccessTokenType = '', + [string] $AccessTokenType, # Set the access token. [Parameter()] - [securestring] $AccessToken = '', + [securestring] $AccessToken, # Set the access token expiration date. [Parameter()] @@ -69,84 +69,103 @@ # Set the GitHub username. [Parameter()] - [string] $UserName, - - # Force the setting of the configuration item. - [Parameter()] - [switch] $Force + [string] $UserName ) $prefix = $script:SecretVault.Prefix #region AccessToken - $accessTokenGetParam = @{ - Name = "$prefix`AccessToken" - Vault = $script:SecretVault.Name - } - $acessTokenSecretInfo = Get-SecretInfo @accessTokenGetParam - $currentAccessTokenMetadata = $acessTokenSecretInfo.Metadata - - [hashtable]$accessTokenMetadata = $PSBoundParameters.Keys | ForEach-Object { - @{ - Name = $_ - Value = $PSBoundParameters[$_] + $secretName = "$prefix`AccessToken" + $removeKeys = 'AccessToken', 'RefreshToken', 'RefreshTokenExpirationDate' + $keepTypes = 'String', 'Int', 'DateTime' + + # Get existing metadata if it exists + $newSecretMetadata = @{} + if (Get-SecretInfo -Name $secretName) { + $secretGetInfoParam = @{ + Name = $secretName + Vault = $script:SecretVault.Name } - } - if (-not $Force) { - Remove-EmptyHashTableEntries -Hashtable $accessTokenMetadata + $secretInfo = Get-SecretInfo @secretGetInfoParam + Write-Verbose "$secretName - secretInfo : $($secretInfo | Out-String)" + $secretMetadata = $secretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable + $newSecretMetadata = Join-Hashtable -Main $newSecretMetadata -Overrides $secretMetadata } - 'AccessToken', 'RefreshToken', 'RefreshTokenExpirationDate', 'Force' | ForEach-Object { - if ($accessTokenMetadata.ContainsKey($_)) { - $accessTokenMetadata.Remove($_) + # Get metadata updates from parameters and clean up unwanted data + $updateSecretMetadata = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable + Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" + Write-Verbose "updateSecretMetadataType : $($updateSecretMetadata.GetType())" + Remove-HashTableEntries -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys + Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" + + $newSecretMetadata = Join-HashTable -Main $newSecretMetadata -Overrides $updateSecretMetadata + Write-Verbose "acessTokenSecretMetadata : $($newSecretMetadata | Out-String)" + Write-Verbose "acessTokenSecretMetadataType : $($newSecretMetadata.GetType())" + + if ($AccessToken) { + $accessTokenSetParam = @{ + Name = $secretName + Vault = $script:SecretVault.Name + SecureStringSecret = $AccessToken } + Set-Secret @accessTokenSetParam } - Join-HashTable -Main $currentAccessTokenMetadata -Overrides $accessTokenMetadata - - $accessTokenSetParam = @{ - Name = "$prefix`AccessToken" - Vault = $script:SecretVault.Name - SecureStringSecret = $AccessToken - Metadata = $secretInfo.Metadata + if (Get-SecretInfo -Name $secretName) { + $secretSetInfoParam = @{ + Name = $secretName + Vault = $script:SecretVault.Name + Metadata = $newSecretMetadata + } + Set-SecretInfo @secretSetInfoParam } - Remove-EmptyHashTableEntries -Hashtable $accessTokenSetParam - Set-SecretInfo @accessTokenSetParam #endregion AccessToken #region RefreshToken - $refreshTokenGetParam = @{ - Name = "$prefix`RefreshToken" - Vault = $script:SecretVault.Name - } - $refreshTokenSecretInfo = Get-SecretInfo @refreshTokenGetParam - $currentRefreshTokenMetadata = $refreshTokenSecretInfo.Metadata - - [hashtable]$refreshTokenMetadata = $PSBoundParameters.Keys | ForEach-Object { - @{ - Name = $_ - Value = $PSBoundParameters[$_] + $secretName = "$prefix`RefreshToken" + $removeKeys = 'AccessToken', 'RefreshToken', 'AccessTokenExpirationDate' + + # Get existing metadata if it exists + $newSecretMetadata = @{} + if (Get-SecretInfo -Name $secretName) { + $secretGetInfoParam = @{ + Name = $secretName + Vault = $script:SecretVault.Name } - } - if (-not $Force) { - Remove-EmptyHashTableEntries -Hashtable $refreshTokenMetadata + $secretInfo = Get-SecretInfo @secretGetInfoParam + Write-Verbose "$secretName - secretInfo : $($secretInfo | Out-String)" + $secretMetadata = $secretInfo.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable + $newSecretMetadata = Join-Hashtable -Main $newSecretMetadata -Overrides $secretMetadata } - 'AccessToken', 'RefreshToken', 'AccessTokenExpirationDate', 'Force' | ForEach-Object { - if ($refreshTokenMetadata.ContainsKey($_)) { - $refreshTokenMetadata.Remove($_) + # Get metadata updates from parameters and clean up unwanted data + $updateSecretMetadata = $PSBoundParameters | ConvertFrom-HashTable | ConvertTo-HashTable + Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" + Write-Verbose "updateSecretMetadataType : $($updateSecretMetadata.GetType())" + Remove-HashTableEntries -Hashtable $updateSecretMetadata -KeepTypes $keepTypes -RemoveNames $removeKeys + Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" + + $newSecretMetadata = Join-HashTable -Main $newSecretMetadata -Overrides $updateSecretMetadata + Write-Verbose "acessTokenSecretMetadata : $($newSecretMetadata | Out-String)" + Write-Verbose "acessTokenSecretMetadataType : $($newSecretMetadata.GetType())" + + if ($RefreshToken) { + $accessTokenSetParam = @{ + Name = $secretName + Vault = $script:SecretVault.Name + SecureStringSecret = $AccessToken } + Set-Secret @accessTokenSetParam } - Join-HashTable -Main $currentRefreshTokenMetadata -DestinationHashTable $refreshTokenMetadata - - $refreshTokenSetParam = @{ - Name = "$prefix`RefreshToken" - Vault = $script:SecretVault.Name - SecureStringSecret = $RefreshToken - Metadata = $secretInfo.Metadata + if (Get-SecretInfo -Name $secretName) { + $secretSetInfoParam = @{ + Name = $secretName + Vault = $script:SecretVault.Name + Metadata = $newSecretMetadata + } + Set-SecretInfo @secretSetInfoParam -Verbose } - Remove-EmptyHashTableEntries -Hashtable $refreshTokenSetParam - Set-SecretInfo @refreshTokenSetParam - #endregion RefreshToken + #endregion AccessToken } diff --git a/tools/utilities/Local-Testing.ps1 b/tools/utilities/Local-Testing.ps1 index e42d82ab0..13e9e3fbf 100644 --- a/tools/utilities/Local-Testing.ps1 +++ b/tools/utilities/Local-Testing.ps1 @@ -19,11 +19,11 @@ Get-Variable | Where-Object -Property Module -NE $null | Select-Object Name, Mod Connect-GitHubAccount 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 +Get-GitHubConfig -Name AccessToken +Get-GitHubConfig -Name AccessTokenExpirationDate +Get-GitHubConfig -Name RefreshToken +Get-GitHubConfig -Name RefreshTokenExpirationDate +Get-GitHubConfig -Name ApiBaseUri Invoke-GitHubAPI -Method Get -ApiEndpoint / Get-GitHubMeta Get-GitHubOctocat -S 'Hello, World!' From 6b150f7330dfc4457672c10dd36f2fbb3dec49ae Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 27 Sep 2023 18:15:09 +0200 Subject: [PATCH 11/14] Fix for force switch. It is now implicit --- src/GitHub/private/Config/Reset-GitHubConfig.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 index cd69ddce3..54f0933bc 100644 --- a/src/GitHub/private/Config/Reset-GitHubConfig.ps1 +++ b/src/GitHub/private/Config/Reset-GitHubConfig.ps1 @@ -58,5 +58,5 @@ } } } - Set-GitHubConfig @Settings -Force + Set-GitHubConfig @Settings } From c78660abf4c91daff08fea0c077d8611cc5870f6 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 27 Sep 2023 18:31:07 +0200 Subject: [PATCH 12/14] Fix for getting settings --- src/GitHub/public/Config/Get-GitHubConfig.ps1 | 4 ++-- tools/utilities/Local-Testing.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/GitHub/public/Config/Get-GitHubConfig.ps1 b/src/GitHub/public/Config/Get-GitHubConfig.ps1 index 556b6ce66..bbe32e296 100644 --- a/src/GitHub/public/Config/Get-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Get-GitHubConfig.ps1 @@ -33,10 +33,10 @@ } 'RefreshTokenExpirationDate' { $RefreshTokenData = Get-SecretInfo -Name "$prefix`RefreshToken" - $RefreshTokenData.Metadata.$Name + $RefreshTokenData.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable | Select-Object -ExpandProperty $Name } default { - $AccessTokenData.Metadata.$Name + $AccessTokenData.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable | Select-Object -ExpandProperty $Name } } } diff --git a/tools/utilities/Local-Testing.ps1 b/tools/utilities/Local-Testing.ps1 index 13e9e3fbf..c99643b25 100644 --- a/tools/utilities/Local-Testing.ps1 +++ b/tools/utilities/Local-Testing.ps1 @@ -9,8 +9,8 @@ Get-Module -Name GitHub -ListAvailable $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 +# $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 From c8fc991b979140b3d2e60adc9d0ceacb93cf8bb1 Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 27 Sep 2023 18:48:27 +0200 Subject: [PATCH 13/14] fix how to store tokens and info --- src/GitHub/public/Config/Set-GitHubConfig.ps1 | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/GitHub/public/Config/Set-GitHubConfig.ps1 b/src/GitHub/public/Config/Set-GitHubConfig.ps1 index 06da4e8ad..e4432fa35 100644 --- a/src/GitHub/public/Config/Set-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Set-GitHubConfig.ps1 @@ -100,8 +100,8 @@ Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" $newSecretMetadata = Join-HashTable -Main $newSecretMetadata -Overrides $updateSecretMetadata - Write-Verbose "acessTokenSecretMetadata : $($newSecretMetadata | Out-String)" - Write-Verbose "acessTokenSecretMetadataType : $($newSecretMetadata.GetType())" + Write-Verbose "newSecretMetadata : $($newSecretMetadata | Out-String)" + Write-Verbose "newSecretMetadataType : $($newSecretMetadata.GetType())" if ($AccessToken) { $accessTokenSetParam = @{ @@ -147,16 +147,16 @@ Write-Verbose "updateSecretMetadata : $($updateSecretMetadata | Out-String)" $newSecretMetadata = Join-HashTable -Main $newSecretMetadata -Overrides $updateSecretMetadata - Write-Verbose "acessTokenSecretMetadata : $($newSecretMetadata | Out-String)" - Write-Verbose "acessTokenSecretMetadataType : $($newSecretMetadata.GetType())" + Write-Verbose "newSecretMetadata : $($newSecretMetadata | Out-String)" + Write-Verbose "newSecretMetadataType : $($newSecretMetadata.GetType())" if ($RefreshToken) { - $accessTokenSetParam = @{ + $refreshTokenSetParam = @{ Name = $secretName Vault = $script:SecretVault.Name - SecureStringSecret = $AccessToken + SecureStringSecret = $RefreshToken } - Set-Secret @accessTokenSetParam + Set-Secret @refreshTokenSetParam } if (Get-SecretInfo -Name $secretName) { From 22d1430e0cf59c5f794e06baeafa9f0b3a69731e Mon Sep 17 00:00:00 2001 From: Marius Storhaug Date: Wed, 27 Sep 2023 18:55:11 +0200 Subject: [PATCH 14/14] Fix so that get is taking the correct values --- src/GitHub/public/Config/Get-GitHubConfig.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GitHub/public/Config/Get-GitHubConfig.ps1 b/src/GitHub/public/Config/Get-GitHubConfig.ps1 index bbe32e296..d872ed894 100644 --- a/src/GitHub/public/Config/Get-GitHubConfig.ps1 +++ b/src/GitHub/public/Config/Get-GitHubConfig.ps1 @@ -22,7 +22,6 @@ ) $prefix = $script:SecretVault.Prefix - $AccessTokenData = Get-SecretInfo -Name "$prefix`RefreshToken" switch($Name) { 'AccessToken' { @@ -36,6 +35,7 @@ $RefreshTokenData.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable | Select-Object -ExpandProperty $Name } default { + $AccessTokenData = Get-SecretInfo -Name "$prefix`AccessToken" $AccessTokenData.Metadata | ConvertFrom-HashTable | ConvertTo-HashTable | Select-Object -ExpandProperty $Name } }