diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs index 1d17e581..e6671028 100644 --- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs @@ -31,6 +31,14 @@ namespace Octokit.Reactive /// A list of the orgs's teams s. IObservable GetAll(string org); + /// + /// Returns all s for the current user. + /// + /// Thrown when a general API error occurs. + /// A list of the user's s. + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + IObservable GetAllForCurrent(); + /// /// Returns all members of the given team. /// @@ -63,6 +71,29 @@ namespace Octokit.Reactive /// IObservable Delete(int id); + /// + /// Adds a to a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to add to the team. + /// Thrown if you attempt to add an organization to a team. + /// A result indicating the membership status + IObservable AddMembership(int id, string login); + + /// + /// Removes a from a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to remove from the team. + /// if the user was removed from the team; otherwise. + IObservable RemoveMembership(int id, string login); + /// /// Gets whether the user with the given /// is a member of the team with the given . @@ -70,8 +101,18 @@ namespace Octokit.Reactive /// The team to check. /// The user to check. /// if the user is a member of the team; otherwise. + [Obsolete("Use GetMembership(id, login) to detect pending memberships")] IObservable IsMember(int id, string login); + /// + /// Gets whether the user with the given + /// is a member of the team with the given . + /// + /// The team to check. + /// The user to check. + /// A result indicating the membership status + IObservable GetMembership(int id, string login); + /// /// Returns all team's repositories. /// @@ -79,32 +120,36 @@ namespace Octokit.Reactive /// The team's repositories IObservable GetAllRepositories(int id); - /// - /// Add a member to the team - /// - /// Thrown when a general API error occurs. - /// - IObservable AddMember(int id, string login); - - /// - /// Remove a member from the team - /// - /// Thrown when a general API error occurs. - /// - IObservable RemoveMember(int id, string login); - - /// - /// Add a repository to the team - /// - /// Thrown when a general API error occurs. - /// - IObservable AddRepository(int id, string organization, string repoName); - /// /// Remove a repository from the team /// /// Thrown when a general API error occurs. /// - IObservable RemoveRepository(int id, string organization, string repoName); + IObservable RemoveRepository(int id, string organization, string repoName); + + /// + /// Adds a to a . + /// + /// The team identifier. + /// Org to associate the repo with. + /// Name of the repo. + /// Thrown if you attempt to add a repository to a team that is not owned by the organization. + /// + /// See the API documentation for more information. + /// + /// if the repository was added to the team; otherwise. + IObservable AddRepository(int id, string organization, string repoName); + + /// + /// Gets whether or not the given repository is managed by the given team. + /// + /// The team identifier + /// Owner of the org the team is associated with. + /// Name of the repo. + /// + /// See the API documentation for more information. + /// + /// if the repository is managed by the given team; otherwise. + IObservable IsRepositoryManagedByTeam(int id, string owner, string repo); } } diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs index 9315944a..c4d44985 100644 --- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs +++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs @@ -51,6 +51,16 @@ namespace Octokit.Reactive return _connection.GetAndFlattenAllPages(ApiUrls.OrganizationTeams(org)); } + /// + /// Returns all s for the current user. + /// + /// Thrown when a general API error occurs. + /// A list of the user's s. + public IObservable GetAllForCurrent() + { + return _connection.GetAndFlattenAllPages(ApiUrls.UserTeams()); + } + /// /// Returns all members of the given team. /// @@ -95,6 +105,35 @@ namespace Octokit.Reactive return _client.Delete(id).ToObservable(); } + /// + /// Adds a to a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to add to the team. + /// Thrown if you attempt to add an organization to a team. + /// A result indicating the membership status + public IObservable AddMembership(int id, string login) + { + return _client.AddMembership(id, login).ToObservable(); + } + + /// + /// Removes a from a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to remove from the team. + /// if the user was removed from the team; otherwise. + public IObservable RemoveMembership(int id, string login) + { + return _client.RemoveMembership(id, login).ToObservable(); + } + /// /// Gets whether the user with the given /// is a member of the team with the given . @@ -102,11 +141,24 @@ namespace Octokit.Reactive /// The team to check. /// The user to check. /// if the user is a member of the team; otherwise. + [Obsolete("Use GetMembership(id, login) to detect pending memberships")] public IObservable IsMember(int id, string login) { return _client.IsMember(id, login).ToObservable(); } + /// + /// Gets whether the user with the given + /// is a member of the team with the given . + /// + /// The team to check. + /// The user to check. + /// A result indicating the membership status + public IObservable GetMembership(int id, string login) + { + return _client.GetMembership(id, login).ToObservable(); + } + /// /// Returns all team's repositories. /// @@ -118,43 +170,45 @@ namespace Octokit.Reactive } /// - /// Add a member to the team + /// Adds a to a . /// - /// Thrown when a general API error occurs. - /// - public IObservable AddMember(int id, string login) - { - return _client.AddMember(id, login).ToObservable(); - } - - /// - /// Remove a member from the team - /// - /// Thrown when a general API error occurs. - /// - public IObservable RemoveMember(int id, string login) - { - return _client.RemoveMember(id, login).ToObservable(); - } - - /// - /// Add a repository to the team - /// - /// Thrown when a general API error occurs. - /// - public IObservable AddRepository(int id, string organization, string repoName) + /// The team identifier. + /// Org to associate the repo with. + /// Name of the repo. + /// Thrown if you attempt to add a repository to a team that is not owned by the organization. + /// + /// See the API documentation for more information. + /// + /// if the repository was added to the team; otherwise. + public IObservable AddRepository(int id, string organization, string repoName) { return _client.AddRepository(id, organization, repoName).ToObservable(); } + /// /// Remove a repository from the team /// /// Thrown when a general API error occurs. /// - public IObservable RemoveRepository(int id, string organization, string repoName) + public IObservable RemoveRepository(int id, string organization, string repoName) { return _client.RemoveRepository(id, organization, repoName).ToObservable(); } + + /// + /// Gets whether or not the given repository is managed by the given team. + /// + /// The team identifier + /// Owner of the org the team is associated with. + /// Name of the repo. + /// + /// See the API documentation for more information. + /// + /// if the repository is managed by the given team; otherwise. + public IObservable IsRepositoryManagedByTeam(int id, string owner, string repo) + { + return _client.IsRepositoryManagedByTeam(id, owner, repo).ToObservable(); + } } } diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs index a7377abb..6414d398 100644 --- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs +++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs @@ -3,7 +3,6 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using Octokit; -using Octokit.Tests.Helpers; using Octokit.Tests.Integration; using Xunit; @@ -46,28 +45,29 @@ public class TeamsClientTests } } - public class TheIsMemberMethod + public class TheGetAllForCurrentMethod + { + [IntegrationTest] + public async Task GetsIsMemberWhenAuthenticated() + { + var github = Helper.GetAuthenticatedClient(); + var teams = await github.Organization.Team.GetAllForCurrent(); + Assert.NotEmpty(teams); + } + } + + public class TheGetMembershipMethod { readonly Team team; - public TheIsMemberMethod() + public TheGetMembershipMethod() { var github = Helper.GetAuthenticatedClient(); team = github.Organization.Team.GetAll(Helper.Organization).Result.First(); } - [OrganizationTest(Skip="actually returning the membership information! Maybe because it's a public organization?")] - public async Task FailsWhenNotAuthenticated() - { - var github = Helper.GetAnonymousClient(); - - var e = await Assert.ThrowsAsync(() => github.Organization.Team.IsMember(team.Id, Helper.UserName)); - - Assert.Equal(HttpStatusCode.Unauthorized, e.StatusCode); - } - - [OrganizationTest(Skip = "see https://github.com/octokit/octokit.net/issues/533 for the resolution to this failing test")] + [OrganizationTest] public async Task FailsWhenAuthenticatedWithBadCredentials() { var github = Helper.GetBadCredentialsClient(); @@ -81,9 +81,9 @@ public class TeamsClientTests { var github = Helper.GetAuthenticatedClient(); - var isMember = await github.Organization.Team.IsMember(team.Id, Helper.UserName); + var membership = await github.Organization.Team.GetMembership(team.Id, Helper.UserName); - Assert.True(isMember); + Assert.Equal(TeamMembership.Active, membership); } [OrganizationTest] @@ -91,9 +91,9 @@ public class TeamsClientTests { var github = Helper.GetAuthenticatedClient(); - var isMember = await github.Organization.Team.IsMember(team.Id, "foo"); + var membership = await github.Organization.Team.GetMembership(team.Id, "foo"); - Assert.False(isMember); + Assert.Equal(TeamMembership.NotFound, membership); } } diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs index bf19eb67..52fbe985 100644 --- a/Octokit.Tests/Clients/TeamsClientTests.cs +++ b/Octokit.Tests/Clients/TeamsClientTests.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.Threading.Tasks; using NSubstitute; using Octokit.Tests.Helpers; @@ -21,6 +22,20 @@ namespace Octokit.Tests.Clients } } + public class TheGetMethod + { + [Fact] + public void RequestsTheCorrectlUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + client.Get(1); + + connection.Received().Get(Arg.Is(u => u.ToString() == "teams/1"), null); + } + } + public class TheGetAllMethod { [Fact] @@ -57,7 +72,7 @@ namespace Octokit.Tests.Clients } } - public class TheCreateTeamMethod + public class TheCreateMethod { [Fact] public void RequestsTheCorrectUrl() @@ -121,7 +136,48 @@ namespace Octokit.Tests.Clients } } - public class TheIsMemberMethod + public class TheAddMembershipMethod + { + [Fact] + public async Task RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + + var client = new TeamsClient(connection); + + await client.AddMembership(1, "user"); + + connection.Received().Put>( + Arg.Is(u => u.ToString() == "teams/1/memberships/user"), + Args.Object); + } + + [Fact] + public async Task EnsuresNonNullOrEmptyLogin() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.AddMembership(1, null)); + await Assert.ThrowsAsync(() => client.AddMembership(1, "")); + } + } + + public class TheGetAllForCurrentMethod + { + [Fact] + public void RequestsTheCorrectUrl() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + client.GetAllForCurrent(); + + connection.Received().GetAll(Arg.Is(u => u.ToString() == "user/teams")); + } + } + + public class TheGetMembershipMethod { [Fact] public void EnsuresNonNullLogin() @@ -129,7 +185,7 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new TeamsClient(connection); - Assert.ThrowsAsync(() => client.IsMember(1, null)); + Assert.ThrowsAsync(() => client.GetMembership(1, null)); } [Fact] @@ -138,44 +194,45 @@ namespace Octokit.Tests.Clients var connection = Substitute.For(); var client = new TeamsClient(connection); - Assert.ThrowsAsync(() => client.IsMember(1, "")); + Assert.ThrowsAsync(() => client.GetMembership(1, "")); } } - public class TheAddMemberMethod + public class TheRRemoveMembershipMethod { [Fact] public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new TeamsClient(connection); + client.RemoveMembership(1, "user"); - client.AddMember(1, "user"); - - connection.Received().Put(Arg.Is(u => u.ToString() == "teams/1/memberships/user")); + connection.Connection.Received().Delete(Arg.Is(u => u.ToString() == "teams/1/memberships/user")); } + + [Fact] + public async Task EnsuresNonNullOrEmptyLogin() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + await Assert.ThrowsAsync(() => client.RemoveMembership(1, null)); + await Assert.ThrowsAsync(() => client.RemoveMembership(1, "")); + } + } - public class TheRemoveMemberMethod + public class TheGetAllRepositoriesMethod { [Fact] public void RequestsTheCorrectUrl() { var connection = Substitute.For(); var client = new TeamsClient(connection); - client.RemoveMember(1, "user"); + client.GetAllRepositories(1); - connection.Received().Delete(Arg.Is(u => u.ToString() == "teams/1/memberships/user")); - } - } + connection.Received().GetAll(Arg.Is(u => u.ToString() == "teams/1/repos")); - public class TheGetRepositoriesMethod - { - [Fact] - public void RequestsTheCorrectUrl() - { - var connection = Substitute.For(); - var client = new TeamsClient(connection); client.GetAllRepositories(1); connection.Received().GetAll(Arg.Is(u => u.ToString() == "teams/1/repos")); @@ -191,12 +248,28 @@ namespace Octokit.Tests.Clients var client = new TeamsClient(connection); client.RemoveRepository(1, "org", "repo"); - connection.Received().Delete(Arg.Is(u => u.ToString() == "teams/1/repos/org/repo")); + connection.Connection.Received().Delete(Arg.Is(u => u.ToString() == "teams/1/repos/org/repo")); } } public class TheAddRepositoryMethod { + [Fact] + public async Task EnsuresNonNullOrEmptyArguments() + { + var connection = Substitute.For(); + var client = new TeamsClient(connection); + + // Check owner arguments. + await Assert.ThrowsAsync(() => client.RemoveRepository(1, null, "repoName")); + await Assert.ThrowsAsync(() => client.RemoveRepository(1, "", "repoName")); + + // Check repo arguments. + await Assert.ThrowsAsync(() => client.RemoveRepository(1, "ownerName", null)); + await Assert.ThrowsAsync(() => client.RemoveRepository(1, "ownerName", "")); + } + + [Fact] public void RequestsTheCorrectUrl() { @@ -204,7 +277,7 @@ namespace Octokit.Tests.Clients var client = new TeamsClient(connection); client.AddRepository(1, "org", "repo"); - connection.Received().Put(Arg.Is(u => u.ToString() == "teams/1/repos/org/repo")); + connection.Connection.Received().Put(Arg.Is(u => u.ToString() == "teams/1/repos/org/repo")); } [Fact] @@ -215,15 +288,25 @@ namespace Octokit.Tests.Clients Assert.ThrowsAsync(() => client.AddRepository(1, null, "Repo Name")); } + } + public class TheIsRepositoryManagedByTeamMethod + { [Fact] - public void EnsureNonNullRepo() + public void EnsuresNonNullOrEmptyArguments() { var connection = Substitute.For(); var client = new TeamsClient(connection); Assert.ThrowsAsync(() => client.AddRepository(1, "org name", null)); + // Check owner arguments. + Assert.ThrowsAsync(() => client.IsRepositoryManagedByTeam(1, null, "repoName")); + Assert.ThrowsAsync(() => client.IsRepositoryManagedByTeam(1, "", "repoName")); + + // Check repo arguments. + Assert.ThrowsAsync(() => client.IsRepositoryManagedByTeam(1, "ownerName", null)); + Assert.ThrowsAsync(() => client.IsRepositoryManagedByTeam(1, "ownerName", "")); } } } diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs index 63f40fa2..86c67011 100644 --- a/Octokit/Clients/ITeamsClient.cs +++ b/Octokit/Clients/ITeamsClient.cs @@ -1,4 +1,5 @@ -#if NET_45 +using System; +#if NET_45 using System.Collections.Generic; #endif using System.Threading.Tasks; @@ -33,6 +34,14 @@ namespace Octokit /// A list of the orgs's teams s. Task> GetAll(string org); + /// + /// Returns all s for the current user. + /// + /// Thrown when a general API error occurs. + /// A list of the user's s. + [SuppressMessage("Microsoft.Design", "CA1024:UsePropertiesWhereAppropriate")] + Task> GetAllForCurrent(); + /// /// Returns all members of the given team. /// @@ -64,6 +73,29 @@ namespace Octokit /// Task Delete(int id); + /// + /// Adds a to a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to add to the team. + /// Thrown if you attempt to add an organization to a team. + /// A result indicating the membership status + Task AddMembership(int id, string login); + + /// + /// Removes a from a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to remove from the team. + /// if the user was removed from the team; otherwise. + Task RemoveMembership(int id, string login); + /// /// Gets whether the user with the given /// is a member of the team with the given . @@ -71,21 +103,17 @@ namespace Octokit /// The team to check. /// The user to check. /// if the user is a member of the team; otherwise. + [Obsolete("Use GetMembership(id, login) as this will report on pending requests")] Task IsMember(int id, string login); /// - /// Add a member to the team + /// Gets whether the user with the given + /// is a member of the team with the given . /// - /// Thrown when a general API error occurs. - /// - Task AddMember(int id, string login); - - /// - /// Remove a member from the team - /// - /// Thrown when a general API error occurs. - /// - Task RemoveMember(int id, string login); + /// The team to check. + /// The user to check. + /// A result indicating the membership status + Task GetMembership(int id, string login); /// /// Returns all team's repositories. @@ -99,13 +127,25 @@ namespace Octokit /// /// Thrown when a general API error occurs. /// - Task AddRepository(int id, string organization, string repoName); + Task AddRepository(int id, string organization, string repoName); /// /// Remove a repository from the team /// /// Thrown when a general API error occurs. /// - Task RemoveRepository(int id, string organization, string repoName); + Task RemoveRepository(int id, string organization, string repoName); + + /// + /// Gets whether or not the given repository is managed by the given team. + /// + /// The team identifier + /// Owner of the org the team is associated with. + /// Name of the repo. + /// + /// See the API documentation for more information. + /// + /// if the repository is managed by the given team; otherwise. + Task IsRepositoryManagedByTeam(int id, string owner, string repo); } } diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs index 3cacc7dc..4afab495 100644 --- a/Octokit/Clients/TeamsClient.cs +++ b/Octokit/Clients/TeamsClient.cs @@ -1,12 +1,12 @@ -#if NET_45 +using System; +using System.Net; +#if NET_45 using System.Collections.Generic; #endif using System.Threading.Tasks; -using System.Diagnostics.CodeAnalysis; namespace Octokit { - /// /// A client for GitHub's Organization Teams API. /// @@ -52,6 +52,17 @@ namespace Octokit return ApiConnection.GetAll(endpoint); } + /// + /// Returns all s for the current user. + /// + /// Thrown when a general API error occurs. + /// A list of the user's s. + public Task> GetAllForCurrent() + { + var endpoint = ApiUrls.UserTeams(); + return ApiConnection.GetAll(endpoint); + } + /// /// Returns all members of the given team. /// @@ -67,6 +78,33 @@ namespace Octokit return ApiConnection.GetAll(endpoint); } + /// + /// Gets whether the user with the given + /// is a member of the team with the given . + /// + /// The team to check. + /// The user to check. + /// A result indicating the membership status + public async Task GetMembership(int id, string login) + { + var endpoint = ApiUrls.TeamMember(id, login); + + Dictionary response; + + try + { + response = await ApiConnection.Get>(endpoint); + } + catch (NotFoundException) + { + return TeamMembership.NotFound; + } + + return response["state"] == "active" + ? TeamMembership.Active + : TeamMembership.Pending; + } + /// /// Returns newly created for the current org. /// @@ -102,9 +140,74 @@ namespace Octokit public Task Delete(int id) { var endpoint = ApiUrls.Teams(id); + return ApiConnection.Delete(endpoint); } + /// + /// Adds a to a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to add to the team. + /// Thrown if you attempt to add an organization to a team. + /// A result indicating the membership status + public async Task AddMembership(int id, string login) + { + Ensure.ArgumentNotNullOrEmptyString(login, "login"); + + var endpoint = ApiUrls.TeamMember(id, login); + + Dictionary response; + + try + { + response = await ApiConnection.Put>(endpoint, null); + } + catch (NotFoundException) + { + return TeamMembership.NotFound; + } + + if (response == null || !response.ContainsKey("state")) + { + return TeamMembership.NotFound; + } + + return response["state"] == "active" + ? TeamMembership.Active + : TeamMembership.Pending; + } + + /// + /// Removes a from a . + /// + /// + /// See the API documentation for more information. + /// + /// The team identifier. + /// The user to remove from the team. + /// if the user was removed from the team; otherwise. + public async Task RemoveMembership(int id, string login) + { + Ensure.ArgumentNotNullOrEmptyString(login, "login"); + + var endpoint = ApiUrls.TeamMember(id, login); + + try + { + var httpStatusCode = await ApiConnection.Connection.Delete(endpoint); + + return httpStatusCode == HttpStatusCode.NoContent; + } + catch (NotFoundException) + { + return false; + } + } + /// /// Gets whether the user with the given /// is a member of the team with the given . @@ -112,6 +215,7 @@ namespace Octokit /// The team to check. /// The user to check. /// if the user is a member of the team; otherwise. + [Obsolete("Use GetMembership(id, login) as this will report on pending requests")] public async Task IsMember(int id, string login) { Ensure.ArgumentNotNullOrEmptyString(login, "login"); @@ -121,7 +225,7 @@ namespace Octokit try { var response = await ApiConnection.Connection.GetResponse(endpoint); - return response.HttpResponse.StatusCode == System.Net.HttpStatusCode.NoContent; + return response.HttpResponse.StatusCode == HttpStatusCode.NoContent; } catch (NotFoundException) { @@ -129,30 +233,6 @@ namespace Octokit } } - /// - /// Add a member to the team - /// - /// Thrown when a general API error occurs. - /// - public Task AddMember(int id, string login) - { - Ensure.ArgumentNotNullOrEmptyString(login, "login"); - - var endpoint = ApiUrls.TeamMember(id, login); - return ApiConnection.Put(endpoint); - } - - /// - /// Remove a member from the team - /// - /// Thrown when a general API error occurs. - /// - public Task RemoveMember(int id, string login) - { - Ensure.ArgumentNotNullOrEmptyString(login, "login"); - return ApiConnection.Delete(ApiUrls.TeamMember(id, login)); - } - /// /// Returns all team's repositories. /// @@ -165,18 +245,42 @@ namespace Octokit return ApiConnection.GetAll(endpoint); } + /// + /// Returns all (ies) associated with the given team. + /// + /// The team identifier + /// + /// See the API documentation for more information. + /// + /// A list of the team's (ies). + public Task> GetRepositories(int id) + { + var endpoint = ApiUrls.TeamRepositories(id); + + return ApiConnection.GetAll(endpoint); + } + /// /// Add a repository to the team /// /// Thrown when a general API error occurs. /// - public Task AddRepository(int id, string organization, string repoName) + public async Task AddRepository(int id, string organization, string repoName) { Ensure.ArgumentNotNullOrEmptyString(organization, "organization"); Ensure.ArgumentNotNullOrEmptyString(repoName, "repoName"); var endpoint = ApiUrls.TeamRepository(id, organization, repoName); - return ApiConnection.Put(endpoint); + + try + { + var httpStatusCode = await ApiConnection.Connection.Put(endpoint); + return httpStatusCode == HttpStatusCode.NoContent; + } + catch (NotFoundException) + { + return false; + } } /// @@ -184,13 +288,51 @@ namespace Octokit /// /// Thrown when a general API error occurs. /// - public Task RemoveRepository(int id, string organization, string repoName) + public async Task RemoveRepository(int id, string organization, string repoName) { - Ensure.ArgumentNotNullOrEmptyString(organization, "organization"); + Ensure.ArgumentNotNullOrEmptyString(organization, "owner"); Ensure.ArgumentNotNullOrEmptyString(repoName, "repoName"); var endpoint = ApiUrls.TeamRepository(id, organization, repoName); - return ApiConnection.Delete(endpoint); + + try + { + var httpStatusCode = await ApiConnection.Connection.Delete(endpoint); + + return httpStatusCode == HttpStatusCode.NoContent; + } + catch (NotFoundException) + { + return false; + } + } + + /// + /// Gets whether or not the given repository is managed by the given team. + /// + /// The team identifier + /// Owner of the org the team is associated with. + /// Name of the repo. + /// + /// See the API documentation for more information. + /// + /// if the repository is managed by the given team; otherwise. + public async Task IsRepositoryManagedByTeam(int id, string owner, string repo) + { + Ensure.ArgumentNotNullOrEmptyString(owner, "owner"); + Ensure.ArgumentNotNullOrEmptyString(repo, "repo"); + + var endpoint = ApiUrls.TeamRepository(id, owner, repo); + + try + { + var response = await ApiConnection.Connection.GetResponse(endpoint); + return response.HttpResponse.StatusCode == HttpStatusCode.NoContent; + } + catch (NotFoundException) + { + return false; + } } } } diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs index c569d5aa..3bc5ec9e 100644 --- a/Octokit/Helpers/ApiUrls.cs +++ b/Octokit/Helpers/ApiUrls.cs @@ -1149,9 +1149,20 @@ namespace Octokit } /// - /// returns the for teams + /// Returns the to discover teams + /// for the current user /// - /// + /// + public static Uri UserTeams() + { + return "user/teams".FormatUri(); + } + + /// + /// Returns the for teams + /// use for getting, updating, or deleting a . + /// + /// The id of the . /// public static Uri Teams(int id) { diff --git a/Octokit/Http/JsonHttpPipeline.cs b/Octokit/Http/JsonHttpPipeline.cs index d22f0efb..864136e4 100644 --- a/Octokit/Http/JsonHttpPipeline.cs +++ b/Octokit/Http/JsonHttpPipeline.cs @@ -53,11 +53,11 @@ namespace Octokit.Internal { var typeIsDictionary = typeof(IDictionary).IsAssignableFrom(typeof(T)); var typeIsEnumerable = typeof(IEnumerable).IsAssignableFrom(typeof(T)); - var responseIsArray = body.StartsWith("{", StringComparison.Ordinal); + var responseIsObject = body.StartsWith("{", StringComparison.Ordinal); // If we're expecting an array, but we get a single object, just wrap it. // This supports an api that dynamically changes the return type based on the content. - if (!typeIsDictionary && typeIsEnumerable && responseIsArray) + if (!typeIsDictionary && typeIsEnumerable && responseIsObject) { body = "[" + body + "]"; } diff --git a/Octokit/Models/Response/TeamMembership.cs b/Octokit/Models/Response/TeamMembership.cs new file mode 100644 index 00000000..2dba0d8b --- /dev/null +++ b/Octokit/Models/Response/TeamMembership.cs @@ -0,0 +1,9 @@ +namespace Octokit +{ + public enum TeamMembership + { + NotFound = 0, + Pending = 1, + Active = 2 + } +} diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj index 5e45258c..4bd0ade6 100644 --- a/Octokit/Octokit-Mono.csproj +++ b/Octokit/Octokit-Mono.csproj @@ -394,6 +394,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj index fc48cd45..9110123b 100644 --- a/Octokit/Octokit-MonoAndroid.csproj +++ b/Octokit/Octokit-MonoAndroid.csproj @@ -1,4 +1,4 @@ - + Debug @@ -410,6 +410,7 @@ + \ No newline at end of file diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj index 4fd43be3..8a98670d 100644 --- a/Octokit/Octokit-Monotouch.csproj +++ b/Octokit/Octokit-Monotouch.csproj @@ -1,4 +1,4 @@ - + Debug @@ -403,6 +403,7 @@ + diff --git a/Octokit/Octokit-Portable.csproj b/Octokit/Octokit-Portable.csproj index 72f5e157..4e3d1d8e 100644 --- a/Octokit/Octokit-Portable.csproj +++ b/Octokit/Octokit-Portable.csproj @@ -392,6 +392,7 @@ + diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj index 6936868e..d40ee8b8 100644 --- a/Octokit/Octokit-netcore45.csproj +++ b/Octokit/Octokit-netcore45.csproj @@ -396,6 +396,7 @@ + diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj index 6815ffa1..ca6ab92b 100644 --- a/Octokit/Octokit.csproj +++ b/Octokit/Octokit.csproj @@ -223,6 +223,7 @@ +