diff --git a/Octokit.Reactive/Clients/IObservableTeamsClient.cs b/Octokit.Reactive/Clients/IObservableTeamsClient.cs
index 95d382a9bd..745aa620e3 100644
--- a/Octokit.Reactive/Clients/IObservableTeamsClient.cs
+++ b/Octokit.Reactive/Clients/IObservableTeamsClient.cs
@@ -124,16 +124,54 @@ public interface IObservableTeamsClient
/// Newly created
IObservable Create(string org, NewTeam team);
+ ///
+ /// Updates a team
+ /// To edit a team, the authenticated user must either be an organization owner or a team maintainer
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// updated for the current org
+ IObservable Update(string org, string teamSlug, UpdateTeam team);
+
///
/// Returns updated for the current org.
+ /// This endpoint route is deprecated and will be removed from the Teams API.
+ /// We recommend migrating your existing code to use the new Update a team endpoint.
+ ///
///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
/// Thrown when a general API error occurs.
/// Updated
IObservable Update(int id, UpdateTeam team);
///
- /// Delete a team - must have owner permissions to this
+ /// To delete a team, the authenticated user must be an organization owner or team maintainer.
+ /// If you are an organization owner, deleting a parent team will delete all of its child teams as well.
///
+ ///
+ /// See the API documentation
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// Thrown when a general API error occurs.
+ ///
+ IObservable Delete(string org, string teamSlug);
+
+ ///
+ /// Delete a team - must have owner permissions to do this
+ /// This endpoint route is deprecated and will be removed from the Teams API.
+ /// We recommend migrating your existing code to use the new Delete a team endpoint.
+ /// .
+ ///
+ ///
+ /// See the API documentation
+ ///
+ /// The unique identifier of the team.
/// Thrown when a general API error occurs.
///
IObservable Delete(int id);
@@ -257,5 +295,72 @@ public interface IObservableTeamsClient
/// Options to change API behaviour.
///
IObservable GetAllPendingInvitations(int id, ApiOptions options);
+
+ ///
+ /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository.
+ /// Repositories inherited through a parent team will also be checked.
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ ///
+ IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo);
+
+ ///
+ /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository.
+ /// Repositories inherited through a parent team will also be checked.
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ /// Thrown when a general API error occurs.
+ ///
+ IObservable CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(string org, string teamSlug, string owner, string repo);
+
+ ///
+ /// Add or update team repository permissions
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ ///
+ /// The permission to grant the team on this repository. We accept the following permissions to be set:
+ /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the
+ /// owning organization has defined any. If no permission is specified, the team's permission attribute
+ /// will be used to determine what permission to grant the team on this repository
+ ///
+ /// Thrown when a general API error occurs.
+ ///
+ IObservable AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission);
+
+ ///
+ /// Remove a repository from a team
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ /// Thrown when a general API error occurs.
+ ///
+ IObservable RemoveRepositoryFromATeam(string org, string teamSlug, string owner, string repo);
}
}
diff --git a/Octokit.Reactive/Clients/ObservableTeamsClient.cs b/Octokit.Reactive/Clients/ObservableTeamsClient.cs
index 9fa0d3f7ba..f068d468bb 100644
--- a/Octokit.Reactive/Clients/ObservableTeamsClient.cs
+++ b/Octokit.Reactive/Clients/ObservableTeamsClient.cs
@@ -193,9 +193,34 @@ public IObservable Create(string org, NewTeam team)
return _client.Create(org, team).ToObservable();
}
+ ///
+ /// Updates a team
+ /// To edit a team, the authenticated user must either be an organization owner or a team maintainer
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// updated for the current org
+ public IObservable Update(string org, string teamSlug, UpdateTeam team)
+ {
+ Ensure.ArgumentNotNull(org, nameof(org));
+ Ensure.ArgumentNotNull(teamSlug, nameof(teamSlug));
+ Ensure.ArgumentNotNull(team, nameof(team));
+
+ return _client.Update(org, teamSlug, team).ToObservable();
+ }
+
///
/// Returns updated for the current org.
+ /// This endpoint route is deprecated and will be removed from the Teams API.
+ /// We recommend migrating your existing code to use the new Update a team endpoint.
+ /// .
///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
/// Thrown when a general API error occurs.
/// Updated
public IObservable Update(int id, UpdateTeam team)
@@ -206,8 +231,34 @@ public IObservable Update(int id, UpdateTeam team)
}
///
- /// Delete a team - must have owner permissions to this
+ /// To delete a team, the authenticated user must be an organization owner or team maintainer.
+ /// If you are an organization owner, deleting a parent team will delete all of its child teams as well.
+ ///
+ ///
+ /// See the API documentation
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// Thrown when a general API error occurs.
+ ///
+ public IObservable Delete(string org, string teamSlug)
+ {
+ Ensure.ArgumentNotNull(org, nameof(org));
+ Ensure.ArgumentNotNull(teamSlug, nameof(teamSlug));
+
+ return _client.Delete(org, teamSlug).ToObservable();
+ }
+
+ ///
+ /// Delete a team - must have owner permissions to do this
+ /// This endpoint route is deprecated and will be removed from the Teams API.
+ /// We recommend migrating your existing code to use the new Delete a team endpoint.
+ /// .
///
+ ///
+ /// See the API documentation
+ ///
+ /// The unique identifier of the team.
/// Thrown when a general API error occurs.
///
public IObservable Delete(int id)
@@ -391,5 +442,86 @@ public IObservable GetAllPendingInvitations(in
return _connection.GetAndFlattenAllPages(ApiUrls.TeamPendingInvitations(id), null, options);
}
+
+ ///
+ /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository.
+ /// Repositories inherited through a parent team will also be checked.
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ ///
+ public IObservable CheckTeamPermissionsForARepository(string org, string teamSlug, string owner, string repo)
+ {
+ return _client.CheckTeamPermissionsForARepository(org, teamSlug, owner, repo).ToObservable();
+ }
+
+ ///
+ /// Checks whether a team has admin, push, maintain, triage, or pull permission for a repository.
+ /// Repositories inherited through a parent team will also be checked.
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ /// Thrown when a general API error occurs.
+ ///
+ public IObservable CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(string org, string teamSlug, string owner, string repo)
+ {
+ return _client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(org, teamSlug, owner, repo).ToObservable();
+ }
+
+ ///
+ /// Add or update team repository permissions
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ ///
+ /// The permission to grant the team on this repository. We accept the following permissions to be set:
+ /// pull, triage, push, maintain, admin and you can also specify a custom repository role name, if the
+ /// owning organization has defined any. If no permission is specified, the team's permission attribute
+ /// will be used to determine what permission to grant the team on this repository
+ ///
+ /// Thrown when a general API error occurs.
+ ///
+ [ManualRoute("PUT", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")]
+ public IObservable AddOrUpdateTeamRepositoryPermissions(string org, string teamSlug, string owner, string repo, string permission)
+ {
+ return _client.AddOrUpdateTeamRepositoryPermissions(org, teamSlug, owner, repo, permission).ToObservable();
+ }
+
+ ///
+ /// Remove a repository from a team
+ ///
+ ///
+ /// See the API Documentation
+ /// for more information.
+ ///
+ /// The organization name. The name is not case sensitive.
+ /// The slug of the team name.
+ /// The account owner of the repository. The name is not case sensitive.
+ /// The name of the repository. The name is not case sensitive.
+ /// Thrown when a general API error occurs.
+ ///
+ [ManualRoute("DELETE", "/orgs/{org}/teams/{team_slug}/repos/{owner}/{repo}")]
+ public IObservable RemoveRepositoryFromATeam(string org, string teamSlug, string owner, string repo)
+ {
+ return _client.RemoveRepositoryFromATeam(org, teamSlug, owner, repo).ToObservable();
+ }
}
}
diff --git a/Octokit.Tests.Conventions/PreviewsTests.cs b/Octokit.Tests.Conventions/PreviewsTests.cs
index 8fd06610c2..6a0fdfa6e4 100644
--- a/Octokit.Tests.Conventions/PreviewsTests.cs
+++ b/Octokit.Tests.Conventions/PreviewsTests.cs
@@ -70,7 +70,8 @@ public void NoStalePreviews()
// https://developer.github.com/v3/repos/commits/#get-a-single-commit
"application/vnd.github.v3.sha",
// https://developer.github.com/v3/activity/starring/#alternative-response-with-star-creation-timestamps
- "application/vnd.github.v3.star+json"
+ "application/vnd.github.v3.star+json",
+ "application/vnd.github.v3.repository+json"
};
var validHeaders = defaultHeaders.Concat(previewAcceptHeaders);
diff --git a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs
index ac9260270c..0735cc2f60 100644
--- a/Octokit.Tests.Integration/Clients/TeamsClientTests.cs
+++ b/Octokit.Tests.Integration/Clients/TeamsClientTests.cs
@@ -1,6 +1,5 @@
using System;
using System.Linq;
-using System.Net;
using System.Threading.Tasks;
using Octokit;
using Octokit.Tests.Integration;
@@ -33,10 +32,12 @@ public async Task CreatesTeam()
Assert.Equal(teamName, team.Name);
Assert.Equal(teamDescription, team.Description);
Assert.Equal(TeamPrivacy.Closed, team.Privacy);
+ // Permission defaults to pull when no permission is specified when creating a team
+ Assert.Equal("pull", team.Permission);
Assert.Equal(1, team.MembersCount);
Assert.Equal(1, team.ReposCount);
- await github.Organization.Team.Delete(team.Id);
+ await github.Organization.Team.Delete(Helper.Organization, team.Slug);
}
}
}
@@ -445,10 +446,49 @@ public async Task UpdatesTeam()
{
var teamName = Helper.MakeNameWithTimestamp("updated-team");
var teamDescription = Helper.MakeNameWithTimestamp("updated description");
+
var update = new UpdateTeam(teamName)
{
Description = teamDescription,
Privacy = TeamPrivacy.Closed,
+ Permission = TeamPermission.Push,
+ ParentTeamId = parentTeamContext.TeamId
+ };
+
+ var team = await _github.Organization.Team.Update(Helper.Organization, teamContext.Team.Slug, update);
+
+ Assert.Equal(teamName, team.Name);
+ Assert.Equal(teamDescription, team.Description);
+ Assert.Equal(TeamPrivacy.Closed, team.Privacy);
+ Assert.Equal("push", team.Permission);
+ Assert.Equal(parentTeamContext.TeamId, team.Parent.Id);
+ }
+ }
+ }
+
+ public class TheUpdateLegacyMethod
+ {
+ private readonly IGitHubClient _github;
+
+ public TheUpdateLegacyMethod()
+ {
+ _github = Helper.GetAuthenticatedClient();
+ }
+
+ [OrganizationTest]
+ public async Task UpdatesTeamLegacy()
+ {
+ using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team-fixture"))))
+ {
+ var teamName = Helper.MakeNameWithTimestamp("updated-team");
+ var teamDescription = Helper.MakeNameWithTimestamp("updated description");
+
+ var update = new UpdateTeam(teamName)
+ {
+ Description = teamDescription,
+ Privacy = TeamPrivacy.Closed,
+ Permission = TeamPermission.Push,
ParentTeamId = parentTeamContext.TeamId
};
@@ -457,8 +497,189 @@ public async Task UpdatesTeam()
Assert.Equal(teamName, team.Name);
Assert.Equal(teamDescription, team.Description);
Assert.Equal(TeamPrivacy.Closed, team.Privacy);
+ Assert.Equal("push", team.Permission);
Assert.Equal(parentTeamContext.TeamId, team.Parent.Id);
}
}
}
+
+ public class TheCheckTeamPermissionsForARepositoryMethod
+ {
+ private readonly IGitHubClient github;
+
+ public TheCheckTeamPermissionsForARepositoryMethod()
+ {
+ github = Helper.GetAuthenticatedClient();
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissions()
+ {
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName);
+
+ var teamPermissionResponse = await github.Organization.Team.CheckTeamPermissionsForARepository(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName);
+
+ Assert.True(teamPermissionResponse);
+ }
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissionsReturnsFalseOnNonTeamRepository()
+ {
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ var response = await github.Organization.Team.CheckTeamPermissionsForARepository(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName);
+
+ Assert.False(response);
+ }
+ }
+ }
+
+ public class TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod
+ {
+ private readonly IGitHubClient github;
+
+ public TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod()
+ {
+ github = Helper.GetAuthenticatedClient();
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissionsWithRepositoryMediaTypeInAccepts()
+ {
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName);
+
+ var teamPermission = await github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName);
+
+ Assert.NotNull(teamPermission);
+ Assert.NotNull(teamPermission.Permissions);
+ Assert.True(teamPermission.Permissions.Pull);
+ }
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissionsThrowsNotFoundException()
+ {
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ await Assert.ThrowsAsync(async () =>
+ await github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName));
+ }
+ }
+ }
+
+ public class TheAddOrUpdateTeamRepositoryPermissionsMethod
+ {
+ [OrganizationTest]
+ public async Task AddsTeamRepositoryPermissions()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository"))))
+ {
+ var teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId);
+
+ Assert.Equal(0, teamRepositories.Count);
+
+ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "admin");
+
+ teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId);
+
+ Assert.True(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Admin);
+ }
+ }
+
+ [OrganizationTest]
+ public async Task UpdatesTeamRepositoryPermissions()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository"))))
+ {
+ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "admin");
+
+ var teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId);
+
+ Assert.True(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Admin);
+
+ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "maintain");
+
+ teamRepositories = await github.Organization.Team.GetAllRepositories(teamContext.TeamId);
+
+ Assert.False(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Admin);
+ Assert.True(teamRepositories.First(x => x.Id == repoContext.RepositoryId).Permissions.Maintain);
+ }
+ }
+ }
+
+ public class TheRemoveRepositoryFromATeamMethod
+ {
+ [OrganizationTest]
+ public async Task RemovesRepositoryFromATeam()
+ {
+ var github = Helper.GetAuthenticatedClient();
+
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository"))))
+ {
+ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "admin");
+
+ await github.Organization.Team.RemoveRepositoryFromATeam(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName);
+
+ var addedRepo = await github.Organization.Team.GetAllRepositories(teamContext.TeamId);
+
+ Assert.Equal(0, addedRepo.Count);
+ }
+ }
+ }
}
diff --git a/Octokit.Tests.Integration/Helper.cs b/Octokit.Tests.Integration/Helper.cs
index 49ca013140..9c94d78f64 100644
--- a/Octokit.Tests.Integration/Helper.cs
+++ b/Octokit.Tests.Integration/Helper.cs
@@ -190,15 +190,15 @@ public static void DeleteRepo(IConnection connection, string owner, string name)
public static void DeleteTeam(IConnection connection, Team team)
{
if (team != null)
- DeleteTeam(connection, team.Id);
+ DeleteTeam(connection, team.Slug);
}
- public static void DeleteTeam(IConnection connection, int teamId)
+ public static void DeleteTeam(IConnection connection, string slug)
{
try
{
var client = new GitHubClient(connection);
- client.Organization.Team.Delete(teamId).Wait(TimeSpan.FromSeconds(15));
+ client.Organization.Team.Delete(Organization, slug).Wait(TimeSpan.FromSeconds(15));
}
catch { }
}
diff --git a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
index 5c52a61246..506f27cca7 100644
--- a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
+++ b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
@@ -36,6 +36,13 @@ internal static async Task CreateTeamContext(this IObservableGitHub
return new TeamContext(client.Connection, team);
}
+ internal static async Task CreateOrganizationRepositoryContext(this IObservableGitHubClient client, string organizationLogin, NewRepository newRepository)
+ {
+ var repo = await client.Repository.Create(organizationLogin, newRepository);
+
+ return new RepositoryContext(client.Connection, repo);
+ }
+
internal static async Task CreateEnterpriseUserContext(this IObservableGitHubClient client, NewUser newUser)
{
var user = await client.User.Administration.Create(newUser);
diff --git a/Octokit.Tests.Integration/Helpers/TeamContext.cs b/Octokit.Tests.Integration/Helpers/TeamContext.cs
index c04ceb2774..f4cc15a26b 100644
--- a/Octokit.Tests.Integration/Helpers/TeamContext.cs
+++ b/Octokit.Tests.Integration/Helpers/TeamContext.cs
@@ -1,8 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
namespace Octokit.Tests.Integration.Helpers
{
diff --git a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs
index 87431a8f56..a818b20c04 100644
--- a/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs
+++ b/Octokit.Tests.Integration/Reactive/ObservableTeamsClientTests.cs
@@ -386,12 +386,239 @@ public async Task UpdatesTeam()
ParentTeamId = parentTeamContext.TeamId
};
+ var team = await _github.Organization.Team.Update(Helper.Organization, teamContext.Team.Slug, update);
+
+ Assert.Equal(teamName, team.Name);
+ Assert.Equal(teamDescription, team.Description);
+ Assert.Equal(TeamPrivacy.Closed, team.Privacy);
+ Assert.Equal(parentTeamContext.TeamId, team.Parent.Id);
+
+ _github.Organization.Team.Delete(Helper.Organization, team.Slug);
+ }
+ }
+ }
+
+ public class TheUpdateLegacyMethod
+ {
+ private readonly IObservableGitHubClient _github;
+
+ public TheUpdateLegacyMethod()
+ {
+ _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
+ }
+
+ [OrganizationTest]
+ public async Task UpdatesTeamLegacy()
+ {
+ using (var parentTeamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("parent-team"))))
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team-fixture"))))
+ {
+ var teamName = Helper.MakeNameWithTimestamp("updated-team");
+ var teamDescription = Helper.MakeNameWithTimestamp("updated description");
+ var update = new UpdateTeam(teamName)
+ {
+ Description = teamDescription,
+ Privacy = TeamPrivacy.Closed,
+ ParentTeamId = parentTeamContext.TeamId
+ };
+
var team = await _github.Organization.Team.Update(teamContext.TeamId, update);
Assert.Equal(teamName, team.Name);
Assert.Equal(teamDescription, team.Description);
Assert.Equal(TeamPrivacy.Closed, team.Privacy);
Assert.Equal(parentTeamContext.TeamId, team.Parent.Id);
+
+ _github.Organization.Team.Delete(teamContext.TeamId);
+ }
+ }
+ }
+
+ public class TheCheckTeamPermissionsForARepositoryMethod
+ {
+ private readonly IObservableGitHubClient _github;
+ public TheCheckTeamPermissionsForARepositoryMethod()
+ {
+ _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
+
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissions()
+ {
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ _github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName);
+
+ var teamPermissionResponse = await _github.Organization.Team.CheckTeamPermissionsForARepository(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName);
+
+ Assert.True(teamPermissionResponse);
+ }
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissionsReturnsFalseOnNonTeamRepository()
+ {
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ var response = await _github.Organization.Team.CheckTeamPermissionsForARepository(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName);
+
+ Assert.False(response);
+ }
+ }
+ }
+
+ public class TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod
+ {
+ private readonly IObservableGitHubClient _github;
+ public TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod()
+ {
+ _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
+
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissions()
+ {
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ _github.Organization.Team.AddRepository(teamContext.TeamId, Helper.Organization, repositoryContext.RepositoryName);
+
+ var teamPermissionResponse = await _github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName);
+
+ Assert.NotNull(teamPermissionResponse);
+ }
+ }
+
+ [OrganizationTest]
+ public async Task ChecksTeamPermissionsThrowsNotFoundException()
+ {
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repositoryContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("teamrepo"))))
+ {
+ await Assert.ThrowsAsync(async () =>
+ await _github.Organization.Team.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repositoryContext.RepositoryOwner,
+ repositoryContext.RepositoryName));
+ }
+ }
+ }
+
+ public class TheAddOrUpdateTeamRepositoryPermissionsMethod
+ {
+ private readonly IObservableGitHubClient _github;
+
+ public TheAddOrUpdateTeamRepositoryPermissionsMethod()
+ {
+ _github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
+ }
+
+ [OrganizationTest]
+ public async Task AddsTeamRepositoryPermissions()
+ {
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repoContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository"))))
+ {
+ var teamRepository = await _github.Organization.Team
+ .GetAllRepositories(teamContext.TeamId)
+ .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId);
+
+ Assert.Null(teamRepository);
+
+ await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "admin");
+
+ teamRepository = await _github.Organization.Team
+ .GetAllRepositories(teamContext.TeamId)
+ .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId);
+
+ Assert.NotNull(teamRepository);
+ }
+ }
+
+ [OrganizationTest]
+ public async Task UpdatesTeamRepositoryPermissions()
+ {
+ using (var teamContext = await _github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repoContext = await _github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository"))))
+ {
+ await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "admin");
+
+ var teamRepository = await _github.Organization.Team
+ .GetAllRepositories(teamContext.TeamId)
+ .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId);
+
+ Assert.True(teamRepository.Permissions.Admin);
+
+ await _github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "maintain");
+
+ teamRepository = await _github.Organization.Team
+ .GetAllRepositories(teamContext.TeamId)
+ .FirstOrDefaultAsync(x => x.Id == repoContext.RepositoryId);
+
+ Assert.True(teamRepository.Permissions.Maintain);
+ Assert.False(teamRepository.Permissions.Admin);
+ }
+ }
+ }
+
+ public class TheRemoveRepositoryFromATeamMethod
+ {
+ [OrganizationTest]
+ public async Task RemovesRepositoryFromATeam()
+ {
+ var github = new ObservableGitHubClient(Helper.GetAuthenticatedClient());
+
+ using (var teamContext = await github.CreateTeamContext(Helper.Organization, new NewTeam(Helper.MakeNameWithTimestamp("team"))))
+ using (var repoContext = await github.CreateOrganizationRepositoryContext(Helper.Organization, new NewRepository(Helper.MakeNameWithTimestamp("team-repository"))))
+ {
+ await github.Organization.Team.AddOrUpdateTeamRepositoryPermissions(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName,
+ "admin");
+
+ await github.Organization.Team.RemoveRepositoryFromATeam(
+ Helper.Organization,
+ teamContext.Team.Slug,
+ repoContext.RepositoryOwner,
+ repoContext.RepositoryName);
+
+ var addedRepo = await github.Organization.Team.GetAllRepositories(teamContext.TeamId).ToList();
+
+ Assert.Equal(0, addedRepo.Count);
}
}
}
diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs
index a1b7179405..b29e921c07 100644
--- a/Octokit.Tests/Clients/TeamsClientTests.cs
+++ b/Octokit.Tests/Clients/TeamsClientTests.cs
@@ -169,6 +169,36 @@ public void RequestsTheCorrectUrl()
var client = new TeamsClient(connection);
var team = new UpdateTeam("Octokittens");
+ var org = "org";
+ var slug = "slug";
+ client.Update(org, slug , team);
+
+ connection.Received().Patch(
+ Arg.Is(u => u.ToString() == "orgs/org/teams/slug"),
+ team);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.Update(null, "b", new UpdateTeam("update-team")));
+ await Assert.ThrowsAsync(() => client.Update("a", null, new UpdateTeam("update-team")));
+ await Assert.ThrowsAsync(() => client.Update("a", "b", null));
+ }
+ }
+
+ public class TheUpdateTeamLegacyMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+ var team = new UpdateTeam("Octokittens");
+
client.Update(1, team);
connection.Received().Patch(
@@ -187,6 +217,34 @@ public async Task EnsuresNonNullArguments()
}
public class TheDeleteTeamMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ var org = "org";
+ var slug = "slug";
+
+ client.Delete(org, slug);
+
+ connection.Received().Delete(
+ Arg.Is(u => u.ToString() == "orgs/org/teams/slug"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.Delete("a", null));
+ await Assert.ThrowsAsync(() => client.Delete(null, "a"));
+ }
+ }
+
+ public class TheDeleteTeamLegacyMethod
{
[Fact]
public void RequestsTheCorrectUrl()
@@ -413,5 +471,152 @@ public async Task RequestsTheCorrectUrl()
Args.ApiOptions);
}
}
+
+ public class TheCheckTeamPermissionsForARepositoryMethod
+ {
+ [Fact]
+ public async Task EnsuresNonNullOrEmptyArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository(null, "teamSlug", "owner", "repo"));
+ await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository("org", null, "owner", "repo"));
+ await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository("org", "teamSlug", null, "repo"));
+ await Assert.ThrowsAsync(() => client.CheckTeamPermissionsForARepository("org", "teamSlug", "owner", null));
+ }
+
+ [Fact]
+ public async Task RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await client.CheckTeamPermissionsForARepository("org", "teamSlug", "owner", "repo");
+
+ var expected = "/orgs/org/teams/teamSlug/repos/owner/repo";
+
+ connection.Received().Get(Arg.Is(u => u.ToString() == expected));
+ }
+ }
+
+ public class TheCheckTeamPermissionsForARepositoryWithCustomAcceptHeaderMethod
+ {
+ [Fact]
+ public async Task EnsuresNonNullOrEmptyArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await Assert.ThrowsAsync(() =>
+ client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader(null, "teamSlug", "owner", "repo"));
+ await Assert.ThrowsAsync(() =>
+ client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", null, "owner", "repo"));
+ await Assert.ThrowsAsync(() =>
+ client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", "teamSlug", null, "repo"));
+ await Assert.ThrowsAsync(() =>
+ client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", "teamSlug", "owner", null));
+ }
+
+ [Fact]
+ public async Task RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await client.CheckTeamPermissionsForARepositoryWithCustomAcceptHeader("org", "teamSlug", "owner", "repo");
+
+ var expected = "/orgs/org/teams/teamSlug/repos/owner/repo";
+
+ connection.Received().Get(
+ Arg.Is(u => u.ToString() == expected),
+ null,
+ Arg.Is(s => s.Equals("application/vnd.github.v3.repository+json")));
+ }
+ }
+
+ public class TheAddOrUpdateTeamRepositoryPermissionsMethod
+ {
+ [Fact]
+ public async Task EnsuresNonNullOrEmptyArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions(null, "teamSlug", "owner", "repo", "permission"));
+ await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", null, "owner", "repo", "permission"));
+ await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", null, "repo", "permission"));
+ await Assert.ThrowsAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", null, "permission"));
+ }
+
+ [Fact]
+ public async Task EnsuresNullPermissionValueDoesNotThrow()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+ var exception = await Record.ExceptionAsync(() => client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", "repo", null));
+
+ Assert.Null(exception);
+ }
+
+
+ [Fact]
+ public async Task RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+ var permission = "a";
+
+ await client.AddOrUpdateTeamRepositoryPermissions("org", "teamSlug", "owner", "repo", permission);
+
+ var expected = "/orgs/org/teams/teamSlug/repos/owner/repo";
+
+ connection.Received().Put(
+ Arg.Is(u => u.ToString() == expected),
+ Arg.Any