From c2178a4ea2a5f9ef788b465c866094a944a92d92 Mon Sep 17 00:00:00 2001 From: Thomas Lem Date: Tue, 13 Feb 2024 22:11:14 +0100 Subject: [PATCH] feat: Adds cancel invitation * Added api request to cancel an organization invitation * Added tests --------- Co-authored-by: Nick Floyd <139819+nickfloyd@users.noreply.github.com> --- .../IObservableOrganizationMembersClient.cs | 14 ++++++++++- .../ObservableOrganizationMembersClient.cs | 19 +++++++++++++++ .../Clients/OrganizationMembersClientTests.cs | 24 +++++++++++++++++++ ...bservableOrganizationMembersClientTests.cs | 24 +++++++++++++++++++ Octokit/Clients/IOrganizationMembersClient.cs | 12 ++++++++++ Octokit/Clients/OrganizationMembersClient.cs | 19 +++++++++++++++ Octokit/Helpers/ApiUrls.cs | 11 +++++++++ 7 files changed, 122 insertions(+), 1 deletion(-) diff --git a/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs b/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs index 4c80d17f88..8e5a903bc0 100644 --- a/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs +++ b/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs @@ -363,7 +363,19 @@ public interface IObservableOrganizationMembersClient /// Options to change API behaviour /// IObservable GetAllFailedInvitations(string org, ApiOptions options); - + + /// + /// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The login for the organization + /// The unique identifier of the invitation + /// + IObservable CancelOrganizationInvitation(string org, int invitationId); + /// /// Returns all s for the current user. /// diff --git a/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs b/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs index f7616aaceb..e258722c26 100644 --- a/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs +++ b/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs @@ -507,6 +507,25 @@ public IObservable GetAllFailedInvitations(str return _connection.GetAndFlattenAllPages(ApiUrls.OrganizationFailedInvitations(org), null, options); } + /// + /// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The login for the organization + /// The unique identifier of the invitation + /// + [ManualRoute("DELETE", "/orgs/{org}/invitations/{invitation_id}")] + public IObservable CancelOrganizationInvitation(string org, int invitationId) + { + Ensure.ArgumentNotNullOrEmptyString(org, nameof(org)); + Ensure.ArgumentNotNullOrDefault(invitationId, nameof(invitationId)); + + return _client.CancelOrganizationInvitation(org, invitationId).ToObservable(); + } + /// /// Returns all s for the current user. /// diff --git a/Octokit.Tests/Clients/OrganizationMembersClientTests.cs b/Octokit.Tests/Clients/OrganizationMembersClientTests.cs index e920dcb2f2..d09ed836aa 100644 --- a/Octokit.Tests/Clients/OrganizationMembersClientTests.cs +++ b/Octokit.Tests/Clients/OrganizationMembersClientTests.cs @@ -628,5 +628,29 @@ public async Task EnsureNonNullArguments() await Assert.ThrowsAsync(() => client.GetAllPendingInvitations("org", null)); } } + + public class TheCancelOrganizationInvitationMethod + { + [Fact] + public void PostsToCorrectUrl() + { + var connection = Substitute.For(); + var client = new OrganizationMembersClient(connection); + + client.CancelOrganizationInvitation("org", 1); + + connection.Received().Delete(Arg.Is(u => u.ToString() == "orgs/org/invitations/1")); + } + + [Fact] + public async Task EnsureNonNullArguments() + { + var client = new OrganizationMembersClient(Substitute.For()); + + await Assert.ThrowsAsync(() => client.CancelOrganizationInvitation(null, 1)); + await Assert.ThrowsAsync(() => client.CancelOrganizationInvitation("", 1)); + await Assert.ThrowsAsync(() => client.CancelOrganizationInvitation("org", 0)); + } + } } } diff --git a/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs b/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs index b06b3f9e58..6e3e44b435 100644 --- a/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs +++ b/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs @@ -434,5 +434,29 @@ public async Task EnsuresNonNullArguments() await Assert.ThrowsAsync(() => client.GetAllPendingInvitations("org", null).ToTask()); } } + + public class TheCancelOrganizationInvitationMethod + { + [Fact] + public void CancelInvitationFromClientOrganizationMember() + { + var gitHubClient = Substitute.For(); + 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()); + + await Assert.ThrowsAsync(() => client.CancelOrganizationInvitation(null, 1).ToTask()); + await Assert.ThrowsAsync(() => client.CancelOrganizationInvitation("", 1).ToTask()); + await Assert.ThrowsAsync(() => client.CancelOrganizationInvitation("org", 0).ToTask()); + } + } } } diff --git a/Octokit/Clients/IOrganizationMembersClient.cs b/Octokit/Clients/IOrganizationMembersClient.cs index 222e10e558..c16707f9d6 100644 --- a/Octokit/Clients/IOrganizationMembersClient.cs +++ b/Octokit/Clients/IOrganizationMembersClient.cs @@ -370,6 +370,18 @@ public interface IOrganizationMembersClient /// Task> GetAllFailedInvitations(string org, ApiOptions options); + /// + /// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The login for the organization + /// The unique identifier of the invitation + /// + Task CancelOrganizationInvitation(string org, int invitationId); + /// /// Returns all s for the current user. /// diff --git a/Octokit/Clients/OrganizationMembersClient.cs b/Octokit/Clients/OrganizationMembersClient.cs index 2e2de872ac..b5fd87de78 100644 --- a/Octokit/Clients/OrganizationMembersClient.cs +++ b/Octokit/Clients/OrganizationMembersClient.cs @@ -604,6 +604,25 @@ public Task> GetAllFailedInvitat return ApiConnection.GetAll(ApiUrls.OrganizationFailedInvitations(org), null, options); } + /// + /// Cancel an organization invitation. In order to cancel an organization invitation, the authenticated user must be an organization owner. + /// + /// + /// See the API Documentation + /// for more information. + /// + /// The login for the organization + /// The unique identifier of the invitation + /// + [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)); + } + /// /// Returns all s for the current user. /// diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index 483df805be..50b8e1a0e9 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -943,6 +943,17 @@ public static Uri OrganizationFailedInvitations(string org) return "orgs/{0}/failed_invitations".FormatUri(org); } + /// + /// Returns the to cancel an organization invitation + /// + /// The name of the organization + /// The unique identifier of the invitation + /// + public static Uri CancelOrganizationInvitation(string org, int invitationId) + { + return "orgs/{0}/invitations/{1}".FormatUri(org, invitationId); + } + /// /// Returns the that returns all of the outside collaborators of the organization ///