Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Adds cancel invitation #2881

Merged
merged 3 commits into from
Feb 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 13 additions & 1 deletion Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,19 @@ public interface IObservableOrganizationMembersClient
/// <param name="options">Options to change API behaviour</param>
/// <returns></returns>
IObservable<OrganizationMembershipInvitation> GetAllFailedInvitations(string org, ApiOptions options);


/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
IObservable<Unit> CancelOrganizationInvitation(string org, int invitationId);

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
19 changes: 19 additions & 0 deletions Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,25 @@ public IObservable<OrganizationMembershipInvitation> GetAllFailedInvitations(str
return _connection.GetAndFlattenAllPages<OrganizationMembershipInvitation>(ApiUrls.OrganizationFailedInvitations(org), null, options);
}

/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
[ManualRoute("DELETE", "/orgs/{org}/invitations/{invitation_id}")]
public IObservable<Unit> CancelOrganizationInvitation(string org, int invitationId)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNullOrDefault(invitationId, nameof(invitationId));

return _client.CancelOrganizationInvitation(org, invitationId).ToObservable();
}

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
24 changes: 24 additions & 0 deletions Octokit.Tests/Clients/OrganizationMembersClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -628,5 +628,29 @@ public async Task EnsureNonNullArguments()
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllPendingInvitations("org", null));
}
}

public class TheCancelOrganizationInvitationMethod
{
[Fact]
public void PostsToCorrectUrl()
{
var connection = Substitute.For<IApiConnection>();
var client = new OrganizationMembersClient(connection);

client.CancelOrganizationInvitation("org", 1);

connection.Received().Delete(Arg.Is<Uri>(u => u.ToString() == "orgs/org/invitations/1"));
}

[Fact]
public async Task EnsureNonNullArguments()
{
var client = new OrganizationMembersClient(Substitute.For<IApiConnection>());

await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation(null, 1));
await Assert.ThrowsAsync<ArgumentException>(() => client.CancelOrganizationInvitation("", 1));
await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation("org", 0));
}
}
}
}
24 changes: 24 additions & 0 deletions Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -434,5 +434,29 @@ public async Task EnsuresNonNullArguments()
await Assert.ThrowsAsync<ArgumentNullException>(() => client.GetAllPendingInvitations("org", null).ToTask());
}
}

public class TheCancelOrganizationInvitationMethod
{
[Fact]
public void CancelInvitationFromClientOrganizationMember()
{
var gitHubClient = Substitute.For<IGitHubClient>();
var client = new ObservableOrganizationMembersClient(gitHubClient);

client.CancelOrganizationInvitation("org", 1);

gitHubClient.Organization.Member.Received().CancelOrganizationInvitation("org", 1);
}

[Fact]
public async Task EnsuresNonNullArguments()
{
var client = new ObservableOrganizationMembersClient(Substitute.For<IGitHubClient>());

await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation(null, 1).ToTask());
await Assert.ThrowsAsync<ArgumentException>(() => client.CancelOrganizationInvitation("", 1).ToTask());
await Assert.ThrowsAsync<ArgumentNullException>(() => client.CancelOrganizationInvitation("org", 0).ToTask());
}
}
}
}
12 changes: 12 additions & 0 deletions Octokit/Clients/IOrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,18 @@ public interface IOrganizationMembersClient
/// <returns></returns>
Task<IReadOnlyList<OrganizationMembershipInvitation>> GetAllFailedInvitations(string org, ApiOptions options);

/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
Task CancelOrganizationInvitation(string org, int invitationId);

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
19 changes: 19 additions & 0 deletions Octokit/Clients/OrganizationMembersClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -604,6 +604,25 @@ public Task<IReadOnlyList<OrganizationMembershipInvitation>> GetAllFailedInvitat
return ApiConnection.GetAll<OrganizationMembershipInvitation>(ApiUrls.OrganizationFailedInvitations(org), null, options);
}

/// <summary>
/// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner.
/// </summary>
/// <remarks>
/// See the <a href="https://docs.github.com/en/rest/orgs/members#cancel-an-organization-invitation">API Documentation</a>
/// for more information.
/// </remarks>
/// <param name="org">The login for the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
[ManualRoute("DELETE", "/orgs/{org}/invitations/{invitation_id}")]
public Task CancelOrganizationInvitation(string org, int invitationId)
{
Ensure.ArgumentNotNullOrEmptyString(org, nameof(org));
Ensure.ArgumentNotNullOrDefault(invitationId, nameof(invitationId));

return ApiConnection.Delete(ApiUrls.CancelOrganizationInvitation(org, invitationId));
}

/// <summary>
/// Returns all <see cref="OrganizationMembership" />s for the current user.
/// </summary>
Expand Down
11 changes: 11 additions & 0 deletions Octokit/Helpers/ApiUrls.cs
Original file line number Diff line number Diff line change
Expand Up @@ -943,6 +943,17 @@ public static Uri OrganizationFailedInvitations(string org)
return "orgs/{0}/failed_invitations".FormatUri(org);
}

/// <summary>
/// Returns the <see cref="Uri"/> to cancel an organization invitation
/// </summary>
/// <param name="org">The name of the organization</param>
/// <param name="invitationId">The unique identifier of the invitation</param>
/// <returns></returns>
public static Uri CancelOrganizationInvitation(string org, int invitationId)
{
return "orgs/{0}/invitations/{1}".FormatUri(org, invitationId);
}

/// <summary>
/// Returns the <see cref="Uri"/> that returns all of the outside collaborators of the organization
/// </summary>
Expand Down