diff --git a/Octokit.Tests/Clients/TeamsClientTests.cs b/Octokit.Tests/Clients/TeamsClientTests.cs
new file mode 100644
index 00000000..fa224636
--- /dev/null
+++ b/Octokit.Tests/Clients/TeamsClientTests.cs
@@ -0,0 +1,112 @@
+using System;
+using System.Threading.Tasks;
+using NSubstitute;
+using Octokit.Tests.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Clients
+{
+ ///
+ /// Client tests mostly just need to make sure they call the IApiConnection with the correct
+ /// relative Uri. No need to fake up the response. All *those* tests are in ApiConnectionTests.cs.
+ ///
+ public class TeamsClientTests
+ {
+ public class TheConstructor
+ {
+ [Fact]
+ public void EnsuresNonNullArguments()
+ {
+ Assert.Throws(() => new TeamsClient(null));
+ }
+ }
+
+ public class TheGetAllMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ client.GetAllTeams("orgName");
+
+ connection.Received().GetAll(Arg.Is(u => u.ToString() == "orgs/orgName/teams"));
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var teams = new TeamsClient(Substitute.For());
+
+ AssertEx.Throws(async () => await teams.GetAllTeams(null));
+ }
+ }
+
+ public class TheCreateTeamMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+ var team = new NewTeam("Octokittens");
+
+ client.CreateTeam("orgName", team);
+
+ connection.Received().Post(Arg.Is(u => u.ToString() == "orgs/orgName/teams"), team);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ AssertEx.Throws(async () => await
+ client.CreateTeam("", new NewTeam("superstars")));
+ AssertEx.Throws(async () => await
+ client.CreateTeam("name", null));
+ }
+ }
+
+ public class TheUpdateTeamMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+ var team = new UpdateTeam("Octokittens");
+
+ client.UpdateTeam(1, team);
+
+ connection.Received().Patch(Arg.Is(u => u.ToString() == "teams/1"), team);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+
+ AssertEx.Throws(async () => await
+ client.UpdateTeam(1, null));
+ }
+ }
+
+ public class TheDeleteTeamMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new TeamsClient(connection);
+ client.DeleteTeam(1);
+
+ connection.Received().Delete(Arg.Is(u => u.ToString() == "teams/1"));
+ }
+ }
+
+ }
+}
diff --git a/Octokit.Tests/OctoKit.Tests-NetCore45.csproj b/Octokit.Tests/OctoKit.Tests-NetCore45.csproj
index 5545b5e3..7c005989 100644
--- a/Octokit.Tests/OctoKit.Tests-NetCore45.csproj
+++ b/Octokit.Tests/OctoKit.Tests-NetCore45.csproj
@@ -106,6 +106,7 @@
+
diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj
index 7705960e..84daa12e 100644
--- a/Octokit.Tests/Octokit.Tests.csproj
+++ b/Octokit.Tests/Octokit.Tests.csproj
@@ -66,6 +66,7 @@
+
diff --git a/Octokit/Clients/IOrganizationsClient.cs b/Octokit/Clients/IOrganizationsClient.cs
index 917cd7ea..546e5cd2 100644
--- a/Octokit/Clients/IOrganizationsClient.cs
+++ b/Octokit/Clients/IOrganizationsClient.cs
@@ -19,6 +19,11 @@ namespace Octokit
///
IOrganizationMembersClient Member { get; }
+ ///
+ /// Returns a client to manage teams of an organization.
+ ///
+ ITeamsClient Team { get; }
+
///
/// Returns the specified .
///
diff --git a/Octokit/Clients/ITeamsClient.cs b/Octokit/Clients/ITeamsClient.cs
new file mode 100644
index 00000000..3737e484
--- /dev/null
+++ b/Octokit/Clients/ITeamsClient.cs
@@ -0,0 +1,46 @@
+#if NET_45
+using System.Collections.Generic;
+#endif
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+ ///
+ /// A client for GitHub's Org Teams API.
+ ///
+ ///
+ /// See the Orgs API documentation for more information.
+ ///
+ public interface ITeamsClient
+ {
+ ///
+ /// Returns all s for the current org.
+ ///
+ /// Thrown when a general API error occurs.
+ /// A list of the orgs's teams s.
+ Task> GetAllTeams(string org);
+
+ ///
+ /// Returns newly created for the current org.
+ ///
+ /// Thrown when a general API error occurs.
+ /// Newly created
+ Task CreateTeam(string org, NewTeam team);
+
+ ///
+ /// Returns updated for the current org.
+ ///
+ /// Thrown when a general API error occurs.
+ /// Updated
+ Task UpdateTeam(int id, UpdateTeam team);
+
+ ///
+ /// Delte a team - must have owner permissions to this
+ ///
+ /// Thrown when a general API error occurs.
+ ///
+ Task DeleteTeam(int id);
+
+ }
+}
diff --git a/Octokit/Clients/OrganizationsClient.cs b/Octokit/Clients/OrganizationsClient.cs
index 4d214b03..ba7f7c5f 100644
--- a/Octokit/Clients/OrganizationsClient.cs
+++ b/Octokit/Clients/OrganizationsClient.cs
@@ -21,10 +21,16 @@ namespace Octokit
public OrganizationsClient(IApiConnection apiConnection) : base(apiConnection)
{
Member = new OrganizationMembersClient(apiConnection);
+ Team = new TeamsClient(apiConnection);
}
public IOrganizationMembersClient Member { get; private set; }
+ ///
+ /// Returns a client to manage teams of an organization.
+ ///
+ public ITeamsClient Team { get; private set; }
+
///
/// Returns the specified .
///
diff --git a/Octokit/Clients/TeamsClient.cs b/Octokit/Clients/TeamsClient.cs
new file mode 100644
index 00000000..3cd08ba9
--- /dev/null
+++ b/Octokit/Clients/TeamsClient.cs
@@ -0,0 +1,81 @@
+#if NET_45
+using System.Collections.Generic;
+#endif
+using System.Diagnostics.CodeAnalysis;
+using System.Threading.Tasks;
+
+namespace Octokit
+{
+
+ ///
+ /// A client for GitHub's Org Teams API.
+ ///
+ ///
+ /// See the Orgs API documentation for more information.
+ ///
+ public class TeamsClient : ApiClient, ITeamsClient
+ {
+ ///
+ /// Initializes a new GitHub Orgs Team API client.
+ ///
+ /// An API connection.
+ public TeamsClient(IApiConnection apiConnection)
+ : base(apiConnection)
+ {
+ }
+
+ ///
+ /// Returns all s for the current org.
+ ///
+ /// Thrown when a general API error occurs.
+ /// A list of the orgs's teams s.
+ public Task> GetAllTeams(string org)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+
+ var endpoint = "orgs/{0}/teams".FormatUri(org);
+
+ return ApiConnection.GetAll(endpoint);
+ }
+
+
+ ///
+ /// Returns newly created for the current org.
+ ///
+ /// Thrown when a general API error occurs.
+ /// Newly created
+ public Task CreateTeam(string org, NewTeam team)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+ Ensure.ArgumentNotNull(team, "team");
+
+ var endpoint = "orgs/{0}/teams".FormatUri(org);
+
+ return ApiConnection.Post(endpoint, team);
+ }
+
+ ///
+ /// Returns updated for the current org.
+ ///
+ /// Thrown when a general API error occurs.
+ /// Updated
+ public Task UpdateTeam(int id, UpdateTeam team)
+ {
+ Ensure.ArgumentNotNull(team, "team");
+
+ var endpoint = "teams/{0}".FormatUri(id);
+ return ApiConnection.Patch(endpoint, team);
+ }
+
+ ///
+ /// Delte a team - must have owner permissions to this
+ ///
+ /// Thrown when a general API error occurs.
+ ///
+ public Task DeleteTeam(int id)
+ {
+ var endpoint = "teams/{0}".FormatUri(id);
+ return ApiConnection.Delete(endpoint);
+ }
+ }
+}
diff --git a/Octokit/Models/Request/NewTeam.cs b/Octokit/Models/Request/NewTeam.cs
new file mode 100644
index 00000000..64e1ed58
--- /dev/null
+++ b/Octokit/Models/Request/NewTeam.cs
@@ -0,0 +1,34 @@
+using Octokit.Internal;
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ public class NewTeam
+ {
+ public NewTeam(string name)
+ {
+ Name = name;
+ RepoNames = new Collection();
+ Permission = Octokit.Permission.Pull;
+ }
+
+ ///
+ /// team name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// permission associated to this team
+ ///
+ public Permission Permission { get; set; }
+
+ ///
+ /// array of repo_names this team has permissions to
+ ///
+ public Collection RepoNames { get; private set; }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Models/Request/Permission.cs b/Octokit/Models/Request/Permission.cs
new file mode 100644
index 00000000..4a858a2a
--- /dev/null
+++ b/Octokit/Models/Request/Permission.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
+ public enum Permission
+ {
+ ///
+ /// team members can pull, push and administer these repositories.
+ ///
+ Admin,
+
+ ///
+ /// team members can pull and push, but not administer these repositories
+ ///
+ Push,
+
+ ///
+ /// team members can pull, but not push to or administer these repositories
+ ///
+ Pull
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Models/Request/UpdateTeam.cs b/Octokit/Models/Request/UpdateTeam.cs
new file mode 100644
index 00000000..1ef7c728
--- /dev/null
+++ b/Octokit/Models/Request/UpdateTeam.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ public class UpdateTeam
+ {
+ public UpdateTeam(string team)
+ {
+ Name = team;
+ }
+
+ public UpdateTeam(string team, Permission permission)
+ {
+ Name = team;
+ Permission = permission;
+ }
+
+ ///
+ /// team name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// permission for this team
+ ///
+ public Permission? Permission { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Models/Response/Team.cs b/Octokit/Models/Response/Team.cs
new file mode 100644
index 00000000..9d8ce0ef
--- /dev/null
+++ b/Octokit/Models/Response/Team.cs
@@ -0,0 +1,48 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ ///
+ /// organization teams
+ ///
+ public class Team
+ {
+ ///
+ /// url for this team
+ ///
+ public Uri Url { get; set; }
+
+ ///
+ /// team id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// team name
+ ///
+ public string Name { get; set; }
+
+ ///
+ /// permission attached to this team
+ ///
+ public Permission Permission { get; set; }
+
+ ///
+ /// how many members in this team
+ ///
+ public int MembersCount { get; set; }
+
+ ///
+ /// how many repo this team has access to
+ ///
+ public int ReposCount { get; set; }
+
+ ///
+ /// who this team belongs to
+ ///
+ public Organization Organization { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Models/Response/TeamItem.cs b/Octokit/Models/Response/TeamItem.cs
new file mode 100644
index 00000000..7d3343a8
--- /dev/null
+++ b/Octokit/Models/Response/TeamItem.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+
+namespace Octokit
+{
+ ///
+ /// organization teams - used for the list
+ ///
+ public class TeamItem
+ {
+ ///
+ /// team id
+ ///
+ public int Id { get; set; }
+
+ ///
+ /// team name
+ ///
+ public string Name { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/Octokit/Octokit-Mono.csproj b/Octokit/Octokit-Mono.csproj
index 5473ddd6..4b2ae820 100644
--- a/Octokit/Octokit-Mono.csproj
+++ b/Octokit/Octokit-Mono.csproj
@@ -58,9 +58,11 @@
+
+
@@ -72,7 +74,10 @@
+
+
+
@@ -94,6 +99,8 @@
+
+
diff --git a/Octokit/Octokit-MonoAndroid.csproj b/Octokit/Octokit-MonoAndroid.csproj
index 556fe0dd..0847f4a8 100644
--- a/Octokit/Octokit-MonoAndroid.csproj
+++ b/Octokit/Octokit-MonoAndroid.csproj
@@ -206,6 +206,13 @@
+
+
+
+
+
+
+
diff --git a/Octokit/Octokit-Monotouch.csproj b/Octokit/Octokit-Monotouch.csproj
index 43a8e561..37824954 100644
--- a/Octokit/Octokit-Monotouch.csproj
+++ b/Octokit/Octokit-Monotouch.csproj
@@ -201,6 +201,13 @@
+
+
+
+
+
+
+
diff --git a/Octokit/Octokit-netcore45.csproj b/Octokit/Octokit-netcore45.csproj
index 24a83d44..4269348c 100644
--- a/Octokit/Octokit-netcore45.csproj
+++ b/Octokit/Octokit-netcore45.csproj
@@ -79,6 +79,7 @@
+
@@ -89,6 +90,7 @@
+
@@ -152,10 +154,13 @@
+
+
+
@@ -189,6 +194,8 @@
+
+
diff --git a/Octokit/Octokit.csproj b/Octokit/Octokit.csproj
index da8d975e..e4f6eb58 100644
--- a/Octokit/Octokit.csproj
+++ b/Octokit/Octokit.csproj
@@ -59,6 +59,8 @@
+
+
@@ -80,6 +82,8 @@
+
+
@@ -87,6 +91,9 @@
+
+
+