Skip to content

Commit 5f1fb3d

Browse files
authored
Allow Initialize-Blogger to be cancelled (#45)
* Add cancellation to auth flow #44 * use environment variables when running locally
1 parent 06d17f3 commit 5f1fb3d

3 files changed

Lines changed: 86 additions & 35 deletions

File tree

src/private/AuthWebServer.ps1

Lines changed: 43 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,60 @@ Function Wait-GoogleAuthApiToken
1313
$HttpListener.Start()
1414

1515
$authCodeReceived = $False
16-
16+
1717
while ($HttpListener.IsListening -and -not $authCodeReceived) {
18-
$HttpContext = $HttpListener.GetContext()
19-
$HttpRequest = $HttpContext.Request
20-
$Query = $HttpRequest.QueryString
18+
# Use async method with timeout to allow for cancellation
19+
$contextTask = $HttpListener.GetContextAsync()
20+
21+
# Wait for either a request or cancellation (check every 500ms)
22+
while (-not $contextTask.IsCompleted) {
23+
Start-Sleep -Milliseconds 500
24+
25+
# Check if user pressed Ctrl+C by testing if we can write to console
26+
try {
27+
[Console]::TreatControlCAsInput = $false
28+
if ([Console]::KeyAvailable) {
29+
$key = [Console]::ReadKey($true)
30+
if ($key.Key -eq 'C' -and $key.Modifiers -eq 'Control') {
31+
Write-Information "`nCancellation requested. Stopping auth server..."
32+
return $null
33+
}
34+
}
35+
}
36+
catch {
37+
# Ignore console access errors
38+
}
39+
}
40+
41+
if ($contextTask.IsCompleted) {
42+
$HttpContext = $contextTask.Result
43+
$HttpRequest = $HttpContext.Request
44+
$Query = $HttpRequest.QueryString
2145

22-
if ($null -ne $Query["code"]) {
23-
$authCode = $Query["code"]
24-
Write-Output $authCode
25-
Write-Verbose "Received auth-code: $authCode"
26-
$authCodeReceived = $true
46+
if ($null -ne $Query["code"]) {
47+
$authCode = $Query["code"]
48+
Write-Output $authCode
49+
Write-Verbose "Received auth-code: $authCode"
50+
$authCodeReceived = $true
2751

28-
# Send "Thanks!"
29-
$buffer = [System.Text.Encoding]::UTF8.GetBytes("<html><body>Good Job! Successfully authorized PSBlogger. You can close this browser window now.</body></html>")
30-
$response = $HttpContext.Response
31-
$response.ContentLength64 = $buffer.Length
32-
$output = $response.OutputStream;
33-
$output.Write($buffer,0,$buffer.Length)
34-
$output.Close() | Write-Verbose
35-
}
52+
# Send "Thanks!"
53+
$buffer = [System.Text.Encoding]::UTF8.GetBytes("<html><body>Good Job! Successfully authorized PSBlogger. You can close this browser window now.</body></html>")
54+
$response = $HttpContext.Response
55+
$response.ContentLength64 = $buffer.Length
56+
$output = $response.OutputStream;
57+
$output.Write($buffer,0,$buffer.Length)
58+
$output.Close() | Write-Verbose
59+
}
60+
}
3661
}
37-
3862
Write-Verbose "Stopping HttpListener."
3963
$HttpListener.Stop()
4064
Write-Verbose "Stopped HttpListener."
4165
}
4266
catch {
4367
# TODO: Catch Permission denied error and warn about running from an elevated prompt
4468
# or add Requires -Administrator
45-
Write-Error $_.ToString()
69+
Write-Error $_.ToString() -ErrorAction Stop
4670
}
4771
finally {
4872
if ($null -ne $HttpListener) {

src/public/Initialize-Blogger.ps1

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,14 @@
66
This prepares your system to use Pandoc + Blogger together by obtaining an authtoken that is
77
authorized to communicate with blogger.
88
9-
.PARAMETER clientId
9+
.PARAMETER ClientId
1010
Google API Client ID. This currently defaults to the one I use, but you
1111
will need to create your own until the Google Application is published and verified
1212
13-
.PARAMETER clientSecret
13+
.PARAMETER ClientSecret
1414
Google API Client Secret. A default value is provided, but you can provide your own if you don't trust me.
1515
16-
.PARAMETER redirectUri
16+
.PARAMETER RedirectUri
1717
The oAuth redirect URL specifed in the Google API Consent Form.
1818
1919
.EXAMPLE
@@ -23,45 +23,64 @@ Initiate a login flow with Google
2323
2424
#>
2525
Function Initialize-Blogger {
26+
[CmdletBinding()]
2627
Param(
2728
[Parameter(HelpMessage = "Google API ClientId")]
28-
[string]$clientId = "<<CLIENT_ID>>",
29+
[string]$ClientId = "<<CLIENT_ID>>",
2930

3031
[Parameter(HelpMessage = "Google API Client Secret")]
31-
[string]$clientSecret = "<<CLIENT_SECRET>>",
32+
[string]$ClientSecret = "<<CLIENT_SECRET>>",
3233

3334
[Parameter(HelpMessage = "Redirect Uri specified in Google API Consent Form")]
34-
[string]$redirectUri = "http://localhost/oauth2callback"
35+
[string]$RedirectUri = "http://localhost/oauth2callback"
3536
)
3637

3738
$ErrorActionPreference = 'Stop'
39+
if ($env:PSBLOGGER_CLIENT_ID -and !$PSBoundParameters.ContainsKey("ClientId"))
40+
{
41+
Write-Verbose "Using environment variable PSBLOGGER_CLIENT_ID for ClientId"
42+
$ClientId = $env:PSBLOGGER_CLIENT_ID
43+
}
44+
if ($env:PSBLOGGER_CLIENT_SECRET -and !$PSBoundParameters.ContainsKey("ClientSecret"))
45+
{
46+
Write-Verbose "Using environment variable PSBLOGGER_CLIENT_SECRET for ClientSecret"
47+
$ClientSecret = $env:PSBLOGGER_CLIENT_SECRET
48+
}
49+
if ($ClientId -eq "<<CLIENT_ID>>" -or $ClientSecret -eq "<<CLIENT_SECRET>>") {
50+
Write-Error "See contribution guide for how to set up your own Google API for local development."
51+
return
52+
}
3853

3954
Write-Information "Let's get an auth-code."
4055

4156
# specify the scopes we want in our auth token
4257
$scope = @(
4358
"https://www.googleapis.com/auth/blogger"
4459
"https://www.googleapis.com/auth/drive.file"
45-
4660
) -join " "
4761

48-
$url = "https://accounts.google.com/o/oauth2/auth?client_id=$clientId&scope=$scope&response_type=code&redirect_uri=$redirectUri&access_type=offline&approval_prompt=force"
62+
$url = "https://accounts.google.com/o/oauth2/auth?client_id=$ClientId&scope=$scope&response_type=code&redirect_uri=$RedirectUri&access_type=offline&approval_prompt=force"
4963

5064
Start-Process $url
5165

5266
$code = Wait-GoogleAuthApiToken
5367

68+
if ($null -eq $code) {
69+
Write-Information "Authentication cancelled by user."
70+
return
71+
}
72+
5473
Write-Information "Sucessfully obtained auth-code!"
5574

5675

5776
# trade the auth-code for an token that has a short-lived expiry
58-
$expiringToken = Get-GoogleAccessToken -clientId $clientId -clientSecret $clientSecret -redirectUri $redirectUri -code $code
77+
$expiringToken = Get-GoogleAccessToken -clientId $ClientId -clientSecret $ClientSecret -redirectUri $RedirectUri -code $code
5978

6079
# use the refresh-token to get an updated access-token
61-
$token = Update-GoogleAccessToken -clientId $clientId -clientSecret $clientSecret -refreshToken $expiringToken.refresh_token
80+
$token = Update-GoogleAccessToken -clientId $ClientId -clientSecret $ClientSecret -refreshToken $expiringToken.refresh_token
6281

6382
# save the token in the credential_cache.json
64-
Set-CredentialCache -clientId $clientId -clientSecret $clientSecret -refreshToken $expiringToken -token $token
65-
83+
Set-CredentialCache -clientId $ClientId -clientSecret $ClientSecret -refreshToken $expiringToken -token $token
84+
6685
Write-Information "Awesome. We're all set."
6786
}

src/tests/Initialize-Blogger.Tests.ps1

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,13 @@ Describe "Initialize-Blogger" {
3232
# arrange
3333
$credentialCache = "TestDrive:\credentialcache.json"
3434
$BloggerSession.CredentialCache = $credentialCache
35-
35+
$initArgs = @{
36+
ClientId = "dummy"
37+
ClientSecret = "dummy"
38+
}
3639

3740
# act
38-
Initialize-Blogger
41+
Initialize-Blogger @initArgs
3942

4043
# assert
4144
$credentials = Get-Content -Path $credentialCache | ConvertFrom-Json
@@ -53,9 +56,14 @@ Describe "Initialize-Blogger" {
5356
$BloggerSession.AccessToken = "invalid"
5457
$BloggerSession.RefreshToken = "invalid"
5558

59+
$initArgs = @{
60+
ClientId = "dummy"
61+
ClientSecret = "dummy"
62+
}
63+
5664
# act
57-
Initialize-Blogger
58-
65+
Initialize-Blogger @initArgs
66+
5967
# assert
6068
$BloggerSession.AccessToken | Should -Be $null
6169
$BloggerSession.RefreshToken | Should -Be $null

0 commit comments

Comments
 (0)