mirror of
https://github.com/zoriya/octokit.net.git
synced 2025-12-20 14:15:12 +00:00
Make credential store awaitable
The storage mechanism for credentials is very likely to be an async data store. So might as well play it safe and make it awaitable.
This commit is contained in:
@@ -33,6 +33,15 @@
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Reactive.Core">
|
||||
<HintPath>..\packages\Rx-Core.2.1.30214.0\lib\Net45\System.Reactive.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Interfaces">
|
||||
<HintPath>..\packages\Rx-Interfaces.2.1.30214.0\lib\Net45\System.Reactive.Interfaces.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Reactive.Linq">
|
||||
<HintPath>..\packages\Rx-Linq.2.1.30214.0\lib\Net45\System.Reactive.Linq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Xml" />
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Octokit.Internal;
|
||||
using Octokit.Tests.Helpers;
|
||||
@@ -23,6 +24,25 @@ namespace Octokit.Tests.Integration
|
||||
|
||||
Assert.Equal("GitHub", user.Company);
|
||||
}
|
||||
|
||||
[IntegrationTest]
|
||||
public async Task ReturnsSpecifiedUserUsingAwaitableCredentialProvider()
|
||||
{
|
||||
var github = new GitHubClient("Octokit Test Runner", new ObservableCredentialProvider());
|
||||
|
||||
// Get a user by username
|
||||
var user = await github.User.Get("tclem");
|
||||
|
||||
Assert.Equal("GitHub", user.Company);
|
||||
}
|
||||
|
||||
class ObservableCredentialProvider : ICredentialStore
|
||||
{
|
||||
public async Task<Credentials> GetCredentials()
|
||||
{
|
||||
return await Observable.Return(AutomationSettings.Current.GitHubCredentials);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TheCurrentMethod
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Rx-Core" version="2.1.30214.0" targetFramework="net45" />
|
||||
<package id="Rx-Interfaces" version="2.1.30214.0" targetFramework="net45" />
|
||||
<package id="Rx-Linq" version="2.1.30214.0" targetFramework="net45" />
|
||||
<package id="xunit" version="1.9.2" targetFramework="net45" />
|
||||
<package id="xunit.extensions" version="1.9.2" targetFramework="net45" />
|
||||
</packages>
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using NSubstitute;
|
||||
using Octokit.Internal;
|
||||
using Xunit;
|
||||
@@ -71,7 +72,7 @@ namespace Octokit.Tests
|
||||
public void IsRetrievedFromCredentialStore()
|
||||
{
|
||||
var credentialStore = Substitute.For<ICredentialStore>();
|
||||
credentialStore.GetCredentials().Returns(new Credentials("foo", "bar"));
|
||||
credentialStore.GetCredentials().Returns(Task.Factory.StartNew(() => new Credentials("foo", "bar")));
|
||||
var client = new GitHubClient("Test Runner", credentialStore);
|
||||
|
||||
Assert.Equal("foo", client.Credentials.Login);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Octokit.Internal
|
||||
{
|
||||
@@ -19,14 +20,11 @@ namespace Octokit.Internal
|
||||
CredentialStore = credentialStore;
|
||||
}
|
||||
|
||||
public void Apply(IRequest request)
|
||||
public async Task Apply(IRequest request)
|
||||
{
|
||||
Ensure.ArgumentNotNull(request, "request");
|
||||
|
||||
// TODO: What if the credentials simply don't exist? We should probably
|
||||
// throw an exception that can be handled and provide guidance to
|
||||
// ICredentialStore implementors.
|
||||
var credentials = CredentialStore.GetCredentials() ?? Credentials.Anonymous;
|
||||
var credentials = await CredentialStore.GetCredentials() ?? Credentials.Anonymous;
|
||||
authenticators[credentials.AuthenticationType].Authenticate(request, credentials);
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,9 @@ namespace Octokit
|
||||
/// Convenience property for getting and setting credentials.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Setting the credentials will change the <see cref="ICredentialStore"/> to use
|
||||
/// You can use this property if you only have a single hard-coded credential. Otherwise, pass in an
|
||||
/// <see cref="ICredentialStore"/> to the constructor.
|
||||
/// Setting this property will change the <see cref="ICredentialStore"/> to use
|
||||
/// the default <see cref="InMemoryCredentialStore"/> with just these credentials.
|
||||
/// </remarks>
|
||||
public Credentials Credentials
|
||||
|
||||
@@ -171,9 +171,23 @@ namespace Octokit.Internal
|
||||
get { return _authenticator.CredentialStore; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience property for getting and setting credentials.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// You can use this property if you only have a single hard-coded credential. Otherwise, pass in an
|
||||
/// <see cref="ICredentialStore"/> to the constructor.
|
||||
/// Setting this property will change the <see cref="ICredentialStore"/> to use
|
||||
/// the default <see cref="InMemoryCredentialStore"/> with just these credentials.
|
||||
/// </remarks>
|
||||
public Credentials Credentials
|
||||
{
|
||||
get { return CredentialStore.GetCredentials() ?? Credentials.Anonymous; }
|
||||
get
|
||||
{
|
||||
var credentialTask = CredentialStore.GetCredentials();
|
||||
if (credentialTask == null) return Credentials.Anonymous;
|
||||
return credentialTask.Result ?? Credentials.Anonymous;
|
||||
}
|
||||
// Note this is for convenience. We probably shouldn't allow this to be mutable.
|
||||
set
|
||||
{
|
||||
@@ -200,7 +214,7 @@ namespace Octokit.Internal
|
||||
async Task<IResponse<T>> RunRequest<T>(IRequest request)
|
||||
{
|
||||
request.Headers.Add("User-Agent", UserAgent);
|
||||
_authenticator.Apply(request);
|
||||
await _authenticator.Apply(request);
|
||||
var response = await _httpClient.Send<T>(request);
|
||||
_apiInfoParser.ParseApiHttpHeaders(response);
|
||||
HandleErrors(response);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Octokit.Internal
|
||||
{
|
||||
public interface ICredentialStore
|
||||
{
|
||||
[SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate",
|
||||
Justification = "The credential store migth not be immediate")]
|
||||
Credentials GetCredentials();
|
||||
Task<Credentials> GetCredentials();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
namespace Octokit.Internal
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Octokit.Internal
|
||||
{
|
||||
public class InMemoryCredentialStore : ICredentialStore
|
||||
{
|
||||
@@ -11,9 +13,9 @@
|
||||
_credentials = credentials;
|
||||
}
|
||||
|
||||
public Credentials GetCredentials()
|
||||
public Task<Credentials> GetCredentials()
|
||||
{
|
||||
return _credentials;
|
||||
return Task.Factory.StartNew(() => _credentials);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user