Skip to content

Commit

Permalink
Merge pull request #1343 from alfhenrik/enh-gpgkeysclient
Browse files Browse the repository at this point in the history
User GPG Keys client
  • Loading branch information
ryangribble committed Jun 8, 2016
2 parents 886dcba + 990ba69 commit ff0112e
Show file tree
Hide file tree
Showing 34 changed files with 1,007 additions and 4 deletions.
71 changes: 71 additions & 0 deletions Octokit.Reactive/Clients/IObservableUserGpgKeysClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive;
using System.Text;
using System.Threading.Tasks;

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's UserUser GPG Keys API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/">User GPG Keys documentation</a> for more information.
/// </remarks>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Gpg")]
public interface IObservableUserGpgKeysClient
{
/// <summary>
/// Gets all GPG keys for the authenticated user.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys">API documentation</a> for more information.
/// </remarks>
/// <returns>A <see cref="IReadOnlyList{GpgKey}"/> of <see cref="GpgKey"/>s for the current user.</returns>
IObservable<GpgKey> GetAllForCurrent();

/// <summary>
/// Gets all GPG keys for the authenticated user.
/// </summary>
/// <param name="options">Options for changing the API response</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys">API documentation</a> for more information.
/// </remarks>
/// <returns>A <see cref="IReadOnlyList{GpgKey}"/> of <see cref="GpgKey"/>s for the current user.</returns>
IObservable<GpgKey> GetAllForCurrent(ApiOptions options);

/// <summary>
/// View extended details of the <see cref="GpgKey"/> for the specified id.
/// </summary>
/// <param name="id">The ID of the GPG key</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#get-a-single-gpg-key">API documentation</a> for more information.
/// </remarks>
/// <returns>The <see cref="GpgKey"/> for the specified ID.</returns>
[SuppressMessage("Microsoft.Naming", "CA1716:IdentifiersShouldNotMatchKeywords", MessageId = "Get")]
IObservable<GpgKey> Get(int id);

/// <summary>
/// Creates a new <see cref="GpgKey"/> for the authenticated user.
/// </summary>
/// <param name="newGpgKey">The new GPG key to add.</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key">API documentation</a> for more information.
/// </remarks>
/// <returns>The newly created <see cref="GpgKey"/>.</returns>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Gpg")]
IObservable<GpgKey> Create(NewGpgKey newGpgKey);

/// <summary>
/// Deletes the GPG key for the specified ID.
/// </summary>
/// <param name="id">The ID of the GPG key to delete.</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key">API documentation</a> for more information.
/// </remarks>
/// <returns></returns>
IObservable<Unit> Delete(int id);
}
}
9 changes: 9 additions & 0 deletions Octokit.Reactive/Clients/IObservableUsersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ public interface IObservableUsersClient
///</remarks>
IObservableUserKeysClient Keys { get; }

/// <summary>
/// A client for GitHub's UserUser GPG Keys API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/">User GPG Keys documentation</a> for more information.
/// </remarks>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Gpg")]
IObservableUserGpgKeysClient GpgKey { get; }

/// <summary>
/// A client for GitHub's User Administration API
/// </summary>
Expand Down
99 changes: 99 additions & 0 deletions Octokit.Reactive/Clients/ObservableUserGpgKeysClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Reactive.Threading.Tasks;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using Octokit.Reactive.Internal;

namespace Octokit.Reactive
{
/// <summary>
/// A client for GitHub's UserUser GPG Keys API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/">User GPG Keys documentation</a> for more information.
/// </remarks>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Gpg")]
public class ObservableUserGpgKeysClient : IObservableUserGpgKeysClient
{
readonly IUserGpgKeysClient _client;

public ObservableUserGpgKeysClient(IGitHubClient client)
{
Ensure.ArgumentNotNull(client, "client");

_client = client.User.GpgKey;
}

/// <summary>
/// Gets all GPG keys for the authenticated user.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys">API documentation</a> for more information.
/// </remarks>
/// <returns>A <see cref="IReadOnlyList{GpgKey}"/> of <see cref="GpgKey"/>s for the current user.</returns>
public IObservable<GpgKey> GetAllForCurrent()
{
return GetAllForCurrent(ApiOptions.None);
}

/// <summary>
/// Gets all GPG keys for the authenticated user.
/// </summary>
/// <param name="options">Options for changing the API response</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#list-your-gpg-keys">API documentation</a> for more information.
/// </remarks>
/// <returns>A <see cref="IReadOnlyList{GpgKey}"/> of <see cref="GpgKey"/>s for the current user.</returns>
public IObservable<GpgKey> GetAllForCurrent(ApiOptions options)
{
return _client.GetAllForCurrent(options).ToObservable().SelectMany(k => k);
}

/// <summary>
/// View extended details of the <see cref="GpgKey"/> for the specified id.
/// </summary>
/// <param name="id">The ID of the GPG key</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#get-a-single-gpg-key">API documentation</a> for more information.
/// </remarks>
/// <returns>The <see cref="GpgKey"/> for the specified ID.</returns>
public IObservable<GpgKey> Get(int id)
{
return _client.Get(id).ToObservable();
}

/// <summary>
/// Creates a new <see cref="GpgKey"/> for the authenticated user.
/// </summary>
/// <param name="newGpgKey">The new GPG key to add.</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#create-a-gpg-key">API documentation</a> for more information.
/// </remarks>
/// <returns>The newly created <see cref="GpgKey"/>.</returns>
public IObservable<GpgKey> Create(NewGpgKey newGpgKey)
{
Ensure.ArgumentNotNull(newGpgKey, "newGpgKey");

return _client.Create(newGpgKey).ToObservable();
}

/// <summary>
/// Deletes the GPG key for the specified ID.
/// </summary>
/// <param name="id">The ID of the GPG key to delete.</param>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/#delete-a-gpg-key">API documentation</a> for more information.
/// </remarks>
/// <returns></returns>
public IObservable<Unit> Delete(int id)
{
return _client.Delete(id).ToObservable();
}
}
}
10 changes: 10 additions & 0 deletions Octokit.Reactive/Clients/ObservableUsersClient.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Reactive.Threading.Tasks;

namespace Octokit.Reactive
Expand All @@ -16,6 +17,7 @@ public ObservableUsersClient(IGitHubClient client)
Followers = new ObservableFollowersClient(client);
Email = new ObservableUserEmailsClient(client);
Keys = new ObservableUserKeysClient(client);
GpgKey = new ObservableUserGpgKeysClient(client);
Administration = new ObservableUserAdministrationClient(client);
}

Expand Down Expand Up @@ -77,6 +79,14 @@ public IObservable<User> Update(UserUpdate user)
///</remarks>
public IObservableUserKeysClient Keys { get; private set; }

/// <summary>
/// A client for GitHub's UserUser GPG Keys API.
/// </summary>
/// <remarks>
/// See the <a href="https://developer.github.com/v3/users/gpg_keys/">User GPG Keys documentation</a> for more information.
/// </remarks>
public IObservableUserGpgKeysClient GpgKey { get; private set; }

/// <summary>
/// A client for GitHub's User Administration API
/// </summary>
Expand Down
4 changes: 3 additions & 1 deletion Octokit.Reactive/Octokit.Reactive-Mono.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@
<Compile Include="Clients\IObservableMigrationsClient.cs" />
<Compile Include="Clients\ObservableMigrationClient.cs" />
<Compile Include="Clients\ObservableMigrationsClient.cs" />
<Compile Include="Clients\IObservableUserGpgKeysClient.cs" />
<Compile Include="Clients\ObservableUserGpgKeysClient.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand All @@ -188,4 +190,4 @@
<Name>Octokit-Mono</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>
4 changes: 3 additions & 1 deletion Octokit.Reactive/Octokit.Reactive-MonoAndroid.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,8 @@
<Compile Include="Clients\IObservableMigrationsClient.cs" />
<Compile Include="Clients\ObservableMigrationClient.cs" />
<Compile Include="Clients\ObservableMigrationsClient.cs" />
<Compile Include="Clients\IObservableUserGpgKeysClient.cs" />
<Compile Include="Clients\ObservableUserGpgKeysClient.cs" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<ItemGroup>
Expand All @@ -196,4 +198,4 @@
<Name>Octokit-MonoAndroid</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>
4 changes: 3 additions & 1 deletion Octokit.Reactive/Octokit.Reactive-Monotouch.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,8 @@
<Compile Include="Clients\IObservableMigrationsClient.cs" />
<Compile Include="Clients\ObservableMigrationClient.cs" />
<Compile Include="Clients\ObservableMigrationsClient.cs" />
<Compile Include="Clients\IObservableUserGpgKeysClient.cs" />
<Compile Include="Clients\ObservableUserGpgKeysClient.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
Expand All @@ -192,4 +194,4 @@
<Name>Octokit-Monotouch</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>
2 changes: 2 additions & 0 deletions Octokit.Reactive/Octokit.Reactive.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
<Compile Include="Clients\IObservableRepositoryDeployKeysClient.cs" />
<Compile Include="Clients\IObservableRepositoryPagesClient.cs" />
<Compile Include="Clients\IObservableUserAdministrationClient.cs" />
<Compile Include="Clients\IObservableUserGpgKeysClient.cs" />
<Compile Include="Clients\IObservableUserKeysClient.cs" />
<Compile Include="Clients\ObservableMigrationsClient.cs" />
<Compile Include="Clients\ObservableMergingClient.cs" />
Expand Down Expand Up @@ -179,6 +180,7 @@
<Compile Include="Clients\ObservableFollowersClient.cs" />
<Compile Include="Clients\ObservableUserAdministrationClient.cs" />
<Compile Include="Clients\ObservableUserEmailsClient.cs" />
<Compile Include="Clients\ObservableUserGpgKeysClient.cs" />
<Compile Include="Clients\ObservableUserKeysClient.cs" />
<Compile Include="Clients\ObservableUsersClient.cs" />
<Compile Include="Clients\IObservableAssigneesClient.cs" />
Expand Down
102 changes: 102 additions & 0 deletions Octokit.Tests.Integration/Clients/UserGpgKeysClientTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Octokit.Tests.Integration.Helpers;
using Xunit;

namespace Octokit.Tests.Integration.Clients
{
public class UserGpgKeysClientTests
{
readonly string knownKeyId = "E88402D2E127A23A";
readonly string knownPublicKey = "xsBNBFdTvCUBCADOaVtPoJTQOgMIVYEpI8uT60LA/kDqw/1OKn7ftKjAtxNVSgjQi/ZqZp8XKjTg2u6l4c/aPjER2BGTg90xCcbmpwq/kkQuHR4DK7dOlEOoTzDDESEFv6XXlXGCnxN8AD8YNvSO+Sy4+35ihuKUBAHDxmOl7ZAMH0STo10KuW82/DhfT3cCJNqmID7H+CW1H6IhwutPKt8XsVq2FQg2RMx+uX1KqkuBAd7b30KJ93SJqzgq5CC3DticaC0/WdZnxmYD01UvMAS6o/REs+SICdsyTxgBx/X8SIXuX2TD9PG/O2785JI5/xvBd4jU6bBH/4oWoHr3e/lyNqb1+GSeTFX3ABEBAAE=";

readonly string publicKey = @"
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: BCPG C# v1.6.1.0
mQENBFdTvCUBCADOaVtPoJTQOgMIVYEpI8uT60LA/kDqw/1OKn7ftKjAtxNVSgjQ
i/ZqZp8XKjTg2u6l4c/aPjER2BGTg90xCcbmpwq/kkQuHR4DK7dOlEOoTzDDESEF
v6XXlXGCnxN8AD8YNvSO+Sy4+35ihuKUBAHDxmOl7ZAMH0STo10KuW82/DhfT3cC
JNqmID7H+CW1H6IhwutPKt8XsVq2FQg2RMx+uX1KqkuBAd7b30KJ93SJqzgq5CC3
DticaC0/WdZnxmYD01UvMAS6o/REs+SICdsyTxgBx/X8SIXuX2TD9PG/O2785JI5
/xvBd4jU6bBH/4oWoHr3e/lyNqb1+GSeTFX3ABEBAAG0AIkBHAQQAQIABgUCV1O8
JQAKCRDohALS4SeiOs/QB/9PMeFNdPkB1xfBm3qvTErqvhTcQspPibucYefG6JHL
vhm6iCOVBeCuPS4P/T8RTzb0qJaTdZZWcwZ9UjRVqF/RKwdMJTBKBHRegc5hRjLH
Koxk0zXosk+CapIR6eVhHe4IzpVVxZOvunsFOclIh+qHx9UzJhz9wSO/XBn/6Rzr
DGzE9fpK1JRKC0I3PuiDCNuZvojXeUsT/zuHYsz00wnA2Em7CmcWWng3nPUSHvBB
GUJ7YE7NvYXqT09PdhoZnf9p1wOugiuG6CLzWf8stlNV3mZptpP+sCGcz/UVffRO
VO/+BCBsaoT4g1FFOmJhbBAD3G72yslBnUJmqKP/39pi
=O7Yi
-----END PGP PUBLIC KEY BLOCK-----
";

[IntegrationTest]
public async Task CanGetAllForCurrentUser()
{
var github = Helper.GetBasicAuthClient();

using (var context = await github.CreateGpgKeyContext())
{
var keys = await github.User.GpgKey.GetAllForCurrent();
Assert.NotEmpty(keys);

var first = keys[0];
Assert.NotNull(first.Id);
Assert.NotNull(first.KeyId);
Assert.NotNull(first.PublicKey);
Assert.Null(first.PrimaryKeyId);
Assert.Empty(first.Subkeys);
}
}

[IntegrationTest]
public async Task CanGetKeyById()
{
var github = Helper.GetBasicAuthClient();
using (var context = await github.CreateGpgKeyContext())
{
var key = await github.User.GpgKey.Get(context.GpgKeyId);

Assert.Equal(context.GpgKeyId, key.Id);
Assert.Equal(context.KeyId, key.KeyId);
Assert.Equal(context.PublicKeyData, key.PublicKey);
}
}

[IntegrationTest]
public async Task CanCreateAndDeleteKey()
{
var github = Helper.GetBasicAuthClient();

var key = await github.User.GpgKey.Create(new NewGpgKey(publicKey));
Assert.NotNull(key);
Assert.Equal(knownPublicKey, key.PublicKey);
Assert.Equal(knownKeyId, key.KeyId);

// Delete the key
await github.User.GpgKey.Delete(key.Id);

// Verify key no longer exists
var keys = await github.User.GpgKey.GetAllForCurrent();
Assert.False(keys.Any(k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey));
}

[IntegrationTest]
public async Task CanNotCreateSameKeyTwice()
{
var github = Helper.GetBasicAuthClient();

var key = await github.User.GpgKey.Create(new NewGpgKey(publicKey));
Assert.NotNull(key);

Assert.ThrowsAsync<ApiValidationException>(async () => await github.User.GpgKey.Create(new NewGpgKey(publicKey)));

await github.User.GpgKey.Delete(key.Id);
var keys = await github.User.GpgKey.GetAllForCurrent();
Assert.False(keys.Any(k => k.KeyId == knownKeyId && k.PublicKey == knownPublicKey));
}
}
}
Loading

0 comments on commit ff0112e

Please sign in to comment.