Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 974fbee

Browse files
author
Meaghan Lewis
authored
Merge branch 'master' into fixes/null-view-model
2 parents b7289a9 + 74303c6 commit 974fbee

File tree

4 files changed

+57
-6
lines changed

4 files changed

+57
-6
lines changed

src/GitHub.Api/IOAuthCallbackListener.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,11 @@ public interface IOAuthCallbackListener
1616
/// <param name="cancel">A cancellation token.</param>
1717
/// <returns>The temporary code included in the callback.</returns>
1818
Task<string> Listen(string id, CancellationToken cancel);
19+
20+
/// <summary>
21+
/// Redirects the last context to respond with listen and stops the underlying http listener
22+
/// </summary>
23+
/// <param name="url">Url to redirect to.</param>
24+
void RedirectLastContext(Uri url);
1925
}
2026
}

src/GitHub.Api/LoginManager.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,8 @@ public async Task<LoginResult> LoginViaOAuth(
157157
await keychain.Save("[oauth]", token.AccessToken, hostAddress).ConfigureAwait(false);
158158
var result = await ReadUserWithRetry(client).ConfigureAwait(false);
159159
await keychain.Save(result.User.Login, token.AccessToken, hostAddress).ConfigureAwait(false);
160+
oauthListener.RedirectLastContext(hostAddress.WebUri.Append(result.User.Login));
161+
160162
return result;
161163
}
162164

src/GitHub.App/Services/OAuthCallbackListener.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
using System.ComponentModel.Composition;
1+
using System;
2+
using System.ComponentModel.Composition;
3+
using System.Diagnostics;
24
using System.Net;
35
using System.Threading;
46
using System.Threading.Tasks;
@@ -39,6 +41,7 @@ public OAuthCallbackListener(IHttpListener httpListener)
3941
}
4042

4143
public readonly static string CallbackUrl = Invariant($"http://localhost:{CallbackPort}/");
44+
private IHttpListenerContext lastContext;
4245

4346
public async Task<string> Listen(string id, CancellationToken cancel)
4447
{
@@ -51,22 +54,29 @@ public async Task<string> Listen(string id, CancellationToken cancel)
5154
{
5255
while (true)
5356
{
54-
var context = await httpListener.GetContextAsync().ConfigureAwait(false);
55-
var foo = context.Request;
56-
var queryParts = HttpUtility.ParseQueryString(context.Request.Url.Query);
57+
lastContext = await httpListener.GetContextAsync().ConfigureAwait(false);
58+
var queryParts = HttpUtility.ParseQueryString(lastContext.Request.Url.Query);
5759

5860
if (queryParts["state"] == id)
5961
{
60-
context.Response.Close();
6162
return queryParts["code"];
6263
}
6364
}
6465
}
6566
}
66-
finally
67+
catch(Exception)
6768
{
6869
httpListener.Stop();
70+
throw;
6971
}
7072
}
73+
74+
public void RedirectLastContext(Uri url)
75+
{
76+
lastContext.Response.Redirect(url);
77+
lastContext.Response.Close();
78+
79+
httpListener.Stop();
80+
}
7181
}
7282
}

test/GitHub.App.UnitTests/Services/OAuthCallbackListenerTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using GitHub.Extensions;
66
using GitHub.Services;
77
using NSubstitute;
8+
using NSubstitute.ExceptionExtensions;
89
using Rothko;
910
using NUnit.Framework;
1011

@@ -32,6 +33,8 @@ public async Task ListenStopsHttpListenerAsync()
3233

3334
await target.Listen("id1", CancellationToken.None);
3435

36+
target.RedirectLastContext(new Uri("http://github.com"));
37+
3538
httpListener.Received(1).Stop();
3639
}
3740

@@ -70,9 +73,39 @@ public async Task SuccessfulResponseClosesResponseAsync()
7073

7174
await target.Listen("id1", CancellationToken.None);
7275

76+
target.RedirectLastContext(new Uri("http://github.com"));
77+
7378
context.Response.Received(1).Close();
7479
}
7580

81+
[Test]
82+
public async Task ContextFailureStopsListener()
83+
{
84+
var httpListener = Substitute.For<IHttpListener>();
85+
httpListener
86+
.When(x => x.Start())
87+
.Do(_ => httpListener.IsListening.Returns(true));
88+
89+
var context = Substitute.For<IHttpListenerContext>();
90+
context.Request.Url.Returns(new Uri($"https://localhost:42549?code=1234&state={"id1"}"));
91+
httpListener.GetContext().Returns(context);
92+
httpListener.GetContextAsync().Returns(context);
93+
94+
httpListener.GetContextAsync().Throws(new Exception());
95+
var target = new OAuthCallbackListener(httpListener);
96+
97+
try
98+
{
99+
await target.Listen("id1", CancellationToken.None);
100+
}
101+
catch (Exception e)
102+
{
103+
104+
}
105+
106+
httpListener.Received(1).Stop();
107+
}
108+
76109
static IHttpListener CreateHttpListener(string id)
77110
{
78111
var result = Substitute.For<IHttpListener>();

0 commit comments

Comments
 (0)