Adding credential-authorization get endpoints (#2556)

This commit is contained in:
Chris Simpson
2022-09-12 21:08:59 +02:00
committed by GitHub
parent 098557b767
commit 063e85e4db
9 changed files with 1082 additions and 582 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -88,5 +88,37 @@ namespace Octokit.Reactive
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <returns>A <see cref="Organization"/></returns>
IObservable<Organization> Update(string org, OrganizationUpdate updateRequest);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
IObservable<OrganizationCredential> GetAllAuthorizations(string org);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
IObservable<OrganizationCredential> GetAllAuthorizations(string org, ApiOptions options);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
IObservable<OrganizationCredential> GetAllAuthorizations(string org, string login);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
IObservable<OrganizationCredential> GetAllAuthorizations(string org, string login, ApiOptions options);
}
}

View File

@@ -144,5 +144,68 @@ namespace Octokit.Reactive
return _client.Update(org, updateRequest).ToObservable();
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
public IObservable<OrganizationCredential> GetAllAuthorizations(string org)
{
Ensure.ArgumentNotNull(org, nameof(org));
var url = ApiUrls.AllOrganizationCredentials(org);
return _connection.GetAndFlattenAllPages<OrganizationCredential>(url);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
public IObservable<OrganizationCredential> GetAllAuthorizations(string org, ApiOptions options)
{
Ensure.ArgumentNotNull(org, nameof(org));
Ensure.ArgumentNotNull(options, nameof(options));
var url = ApiUrls.AllOrganizationCredentials(org);
return _connection.GetAndFlattenAllPages<OrganizationCredential>(url, options);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
public IObservable<OrganizationCredential> GetAllAuthorizations(string org, string login)
{
Ensure.ArgumentNotNull(org, nameof(org));
Ensure.ArgumentNotNull(login, nameof(login));
var url = ApiUrls.AllOrganizationCredentials(org, login);
return _connection.GetAndFlattenAllPages<OrganizationCredential>(url);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
public IObservable<OrganizationCredential> GetAllAuthorizations(string org, string login, ApiOptions options)
{
Ensure.ArgumentNotNull(org, nameof(org));
Ensure.ArgumentNotNull(login, nameof(login));
Ensure.ArgumentNotNull(options, nameof(options));
var url = ApiUrls.AllOrganizationCredentials(org, login);
return _connection.GetAndFlattenAllPages<OrganizationCredential>(url, options);
}
}
}

View File

@@ -192,5 +192,102 @@ namespace Octokit.Tests.Clients
await Assert.ThrowsAsync<ArgumentException>(() => client.Update("", new OrganizationUpdate()));
}
}
public class TheGetAllAuthorizationsMethod
{
[Fact]
public async Task RequestTheCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await client.GetAllAuthorizations("fake");
connection.Received().GetAll<OrganizationCredential>(Arg.Is<Uri>(u => u.ToString() == "orgs/fake/credential-authorizations"));
}
[Fact]
public async Task RequestTheCorrectUrlWithOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await client.GetAllAuthorizations("fake", new ApiOptions() { PageCount = 1, PageSize = 1, StartPage = 1});
connection.Received().GetAll<OrganizationCredential>(Arg.Is<Uri>(u => u.ToString() == "orgs/fake/credential-authorizations"), Args.ApiOptions);
}
[Fact]
public async Task RequestTheCorrectUrlWithLogin()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await client.GetAllAuthorizations("fake", "login");
connection.Received().GetAll<OrganizationCredential>(Arg.Is<Uri>(u => u.ToString() == "orgs/fake/credential-authorizations?login=login"));
}
[Fact]
public async Task RequestTheCorrectUrlWithLoginAndUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await client.GetAllAuthorizations("fake", "login", new ApiOptions() { PageCount = 1, PageSize = 1, StartPage = 1 });
connection.Received().GetAll<OrganizationCredential>(Arg.Is<Uri>(u => u.ToString() == "orgs/fake/credential-authorizations?login=login"), Args.ApiOptions);
}
[Fact]
public async Task EnsuresNonNullArguments()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations(null));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllAuthorizations(""));
}
[Fact]
public async Task EnsuresNonNullArgumentsWithOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations(null, new ApiOptions()));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllAuthorizations("", new ApiOptions()));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations("asd", (ApiOptions)null));
}
[Fact]
public async Task EnsuresNonNullArgumentsWithLogin()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations(null, "asd"));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllAuthorizations("", "asd"));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations("asd", (string)null));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllAuthorizations("asd", ""));
}
[Fact]
public async Task EnsuresNonNullArgumentsWithLoginAndOptions()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationsClient(connection);
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations(null, "asd", new ApiOptions()));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllAuthorizations("", "asd", new ApiOptions()));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations("asd", (string)null, new ApiOptions()));
await Assert.ThrowsAsync<ArgumentException>(() => client.GetAllAuthorizations("asd", "", new ApiOptions()));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllAuthorizations("asd", "asd", null));
}
}
}
}

View File

@@ -153,5 +153,81 @@ namespace Octokit.Tests.Reactive
Assert.Throws<ArgumentException>(() => client.Update("", new OrganizationUpdate()));
}
}
public class TheGetAllAuthorizationsMethod
{
[Fact]
public void RequestsTheCorrectUrl()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationsClient(gitHubClient);
client.GetAllAuthorizations("org");
gitHubClient.Received().Organization.GetAllAuthorizations("org");
}
[Fact]
public void RequestsTheCorrectUrlWithApiOptions()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationsClient(gitHubClient);
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
client.GetAllAuthorizations("org", options);
gitHubClient.Received().Organization.GetAllAuthorizations("org", options);
}
[Fact]
public void RequestsTheCorrectUrlWithLogin()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationsClient(gitHubClient);
client.GetAllAuthorizations("org", "login");
gitHubClient.Received().Organization.GetAllAuthorizations("org", "login");
}
[Fact]
public void RequestsTheCorrectUrlWithApiOptionsWithLogin()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationsClient(gitHubClient);
var options = new ApiOptions
{
StartPage = 1,
PageCount = 1,
PageSize = 1
};
client.GetAllAuthorizations("org", "login", options);
gitHubClient.Received().Organization.GetAllAuthorizations("org", "login", options);
}
[Fact]
public void EnsuresNonNullArguments()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationsClient(gitHubClient);
Assert.Throws<ArgumentNullException>(() => client.GetAllAuthorizations(null));
Assert.Throws<ArgumentNullException>(() => client.GetAllAuthorizations(null, ApiOptions.None));
Assert.Throws<ArgumentNullException>(() => client.GetAllAuthorizations("username", (string)null));
Assert.Throws<ArgumentNullException>(() => client.GetAllAuthorizations("username", null, ApiOptions.None));
Assert.Throws<ArgumentNullException>(() => client.GetAllAuthorizations("asd", (ApiOptions)null));
Assert.Throws<ArgumentNullException>(() => client.GetAllAuthorizations("asd", "asd", null));
}
}
}
}

View File

@@ -113,5 +113,37 @@ namespace Octokit
/// <exception cref="AuthorizationException">Thrown if the client is not authenticated.</exception>
/// <returns>A <see cref="Organization"/></returns>
Task<Organization> Update(string org, OrganizationUpdate updateRequest);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org, ApiOptions options);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org, string login);
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org, string login, ApiOptions options);
}
}

View File

@@ -167,5 +167,73 @@ namespace Octokit
return ApiConnection.Patch<Organization>(updateUri, updateRequest);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
[ManualRoute("GET", "/orgs/{org}/credential-authorizations")]
public Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
var url = ApiUrls.AllOrganizationCredentials(org);
return ApiConnection.GetAll<OrganizationCredential>(url);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
[ManualRoute("GET", "/orgs/{org}/credential-authorizations")]
public Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNull(options, nameof(options));
var url = ApiUrls.AllOrganizationCredentials(org);
return ApiConnection.GetAll<OrganizationCredential>(url, options);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
[ManualRoute("GET", "/orgs/{org}/credential-authorizations")]
public Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org, string login)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNullOrEmptyString(login, nameof(login));
var url = ApiUrls.AllOrganizationCredentials(org, login);
return ApiConnection.GetAll<OrganizationCredential>(url);
}
/// <summary>
/// Returns all <see cref="OrganizationCredential" />s.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <param name="options">Options for changing the API response</param>
/// <returns>A list of <see cref="OrganizationCredential"/>s.</returns>
[ManualRoute("GET", "/orgs/{org}/credential-authorizations")]
public Task<IReadOnlyList<OrganizationCredential>> GetAllAuthorizations(string org, string login, ApiOptions options)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNullOrEmptyString(login, nameof(login));
Ensure.ArgumentNotNull(options, nameof(options));
var url = ApiUrls.AllOrganizationCredentials(org, login);
return ApiConnection.GetAll<OrganizationCredential>(url, options);
}
}
}

View File

@@ -4458,6 +4458,29 @@ namespace Octokit
return "meta".FormatUri();
}
/// <summary>
/// Returns the <see cref="Uri"/> that returns all organization credentials in
/// response to a GET request.
/// </summary>
/// <param name="org">The organization name.</param>
/// <returns>The <see cref="Uri"/> to meta.</returns>
public static Uri AllOrganizationCredentials(string org)
{
return "orgs/{0}/credential-authorizations".FormatUri(org);
}
/// <summary>
/// Returns the <see cref="Uri"/> that returns all organization credentials for a given login in
/// response to a GET request.
/// </summary>
/// <param name="org">The organization name.</param>
/// <param name="login">Limits the list of credentials authorizations for an organization to a specific login</param>
/// <returns>The <see cref="Uri"/> to meta.</returns>
public static Uri AllOrganizationCredentials(string org, string login)
{
return "orgs/{0}/credential-authorizations?login={1}".FormatUri(org, login);
}
/// <summary>
/// Returns the <see cref="Uri"/> for the Packages request
/// </summary>

View File

@@ -0,0 +1,101 @@
using Octokit.Internal;
using System;
using System.Diagnostics;
namespace Octokit
{
[DebuggerDisplay("{DebuggerDisplay,nq}")]
public class OrganizationCredential
{
public OrganizationCredential() { }
public OrganizationCredential(
string login,
long credentialId,
string credentialType,
string tokenLastEight,
DateTime credentialAuthorizedAt,
string[] scopes,
string fingerprint,
DateTime? credentialAccessedAt,
long? authorizedCredentialId,
string authorizedCredentialTitle,
string authorizedCredentialNote,
DateTime? authorizedCredentialExpiresAt)
{
Login = login;
CredentialId = credentialId;
CredentialType = credentialType;
TokenLastEight = tokenLastEight;
CredentialAuthorizedAt = credentialAuthorizedAt;
Scopes = scopes;
Fingerprint = fingerprint;
CredentialAccessedAt = credentialAccessedAt;
AuthorizedCredentialId = authorizedCredentialId;
AuthorizedCredentialTitle = authorizedCredentialTitle;
AuthorizedCredentialNote = authorizedCredentialNote;
AuthorizedCredentialExpiresAt = authorizedCredentialExpiresAt;
}
/// <summary>
/// User login that owns the underlying credential.
/// </summary>
public string Login { get; private set; }
/// <summary>
/// Unique identifier for the credential.
/// </summary>
public long CredentialId { get; private set; }
/// <summary>
/// Human-readable description of the credential type.
/// </summary>
public string CredentialType { get; private set; }
/// <summary>
/// Last eight characters of the credential. Only included in responses with credential_type of personal access token.
/// </summary>
public string TokenLastEight { get; private set; }
/// <summary>
/// Date when the credential was authorized for use.
/// </summary>
public DateTime CredentialAuthorizedAt { get; private set; }
/// <summary>
/// List of oauth scopes the token has been granted.
/// </summary>
public string[] Scopes { get; private set; }
/// <summary>
/// Unique string to distinguish the credential. Only included in responses with credential_type of SSH Key.
/// </summary>
public string Fingerprint { get; private set; }
/// <summary>
/// Date when the credential was last accessed. May be null if it was never accessed
/// </summary>
public DateTime? CredentialAccessedAt { get; private set; }
public long? AuthorizedCredentialId { get; private set; }
/// <summary>
/// The title given to the ssh key. This will only be present when the credential is an ssh key.
/// </summary>
public string AuthorizedCredentialTitle { get; private set; }
/// <summary>
/// The note given to the token. This will only be present when the credential is a token.
/// </summary>
public string AuthorizedCredentialNote { get; private set; }
/// <summary>
/// The expiry for the token. This will only be present when the credential is a token.
/// </summary>
public DateTime? AuthorizedCredentialExpiresAt { get; private set; }
internal string DebuggerDisplay => new SimpleJsonSerializer().Serialize(this);
}
}