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

Commit 7c75c8e

Browse files
author
Steven Kirk
committed
Accept admin:public_key scope.
When checking scopes use some simple logic to allow `admin:public_key` instead of just `write:public_key`. Note that this logic won't account for all the peculiarities of GitHub's scopes but it works for what we need now.
1 parent 28ef265 commit 7c75c8e

File tree

2 files changed

+68
-1
lines changed

2 files changed

+68
-1
lines changed

src/GitHub.Api/LoginManager.cs

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,38 @@ public async Task Logout(HostAddress hostAddress, IGitHubClient client)
194194
await keychain.Delete(hostAddress);
195195
}
196196

197+
/// <summary>
198+
/// Tests if received API scopes match the required API scopes.
199+
/// </summary>
200+
/// <param name="required">The required API scopes.</param>
201+
/// <param name="received">The received API scopes.</param>
202+
/// <returns>True if all required scopes are present, otherwise false.</returns>
203+
public static bool ScopesMatch(IReadOnlyList<string> required, IReadOnlyList<string> received)
204+
{
205+
foreach (var scope in required)
206+
{
207+
var found = received.Contains(scope);
208+
209+
if (!found && (scope.StartsWith("read:") || scope.StartsWith("write:")))
210+
{
211+
// NOTE: Scopes are actually more complex than this, for example
212+
// `user` encompasses `read:user` and `user:email` but just use
213+
// this simple rule for now as it works for the scopes we require.
214+
var adminScope = scope
215+
.Replace("read:", "admin:")
216+
.Replace("write:", "admin:");
217+
found = received.Contains(adminScope);
218+
}
219+
220+
if (!found)
221+
{
222+
return false;
223+
}
224+
}
225+
226+
return true;
227+
}
228+
197229
async Task<ApplicationAuthorization> CreateAndDeleteExistingApplicationAuthorization(
198230
IGitHubClient client,
199231
NewAuthorization newAuth,
@@ -342,7 +374,7 @@ async Task<User> GetUserAndCheckScopes(IGitHubClient client)
342374
.Select(x => x.Trim())
343375
.ToArray();
344376

345-
if (scopes.Except(returnedScopes).Count() == 0)
377+
if (ScopesMatch(scopes, returnedScopes))
346378
{
347379
return response.Body;
348380
}

test/UnitTests/GitHub.Api/LoginManagerTests.cs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,4 +310,39 @@ IGitHubClient CreateClient(User user = null, string[] responseScopes = null)
310310
return result;
311311
}
312312
}
313+
314+
public class TheScopesMatchMethod
315+
{
316+
[Fact]
317+
public void ReturnsFalseWhenMissingScopes()
318+
{
319+
var received = new[] { "user", "repo", "write:public_key" };
320+
321+
Assert.False(LoginManager.ScopesMatch(scopes, received));
322+
}
323+
324+
[Fact]
325+
public void ReturnsTrueWhenScopesEqual()
326+
{
327+
var received = new[] { "user", "repo", "gist", "write:public_key" };
328+
329+
Assert.True(LoginManager.ScopesMatch(scopes, received));
330+
}
331+
332+
[Fact]
333+
public void ReturnsTrueWhenExtraScopesReturned()
334+
{
335+
var received = new[] { "user", "repo", "gist", "foo", "write:public_key" };
336+
337+
Assert.True(LoginManager.ScopesMatch(scopes, received));
338+
}
339+
340+
[Fact]
341+
public void ReturnsTrueWhenAdminScopeReturnedInsteadOfWrite()
342+
{
343+
var received = new[] { "user", "repo", "gist", "foo", "admin:public_key" };
344+
345+
Assert.True(LoginManager.ScopesMatch(scopes, received));
346+
}
347+
}
313348
}

0 commit comments

Comments
 (0)