diff --git a/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs b/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs
new file mode 100644
index 00000000..aa803168
--- /dev/null
+++ b/Octokit.Reactive/Clients/IObservableOrganizationMembersClient.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Octokit.Reactive
+{
+ public interface IObservableOrganizationMembersClient
+ {
+ ///
+ ///
+ /// List all users who are members of an organization. A member is a user that
+ /// belongs to at least 1 team in the organization.
+ ///
+ ///
+ /// If the authenticated user is also an owner of this organization then both
+ /// concealed and public member will be returned.
+ ///
+ ///
+ /// If the requester is not an owner of the organization the query will be redirected
+ /// to the public members list.
+ ///
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ IObservable GetAll(string org);
+
+ ///
+ /// List all users who have publicized their membership of the organization.
+ ///
+ /// http://developer.github.com/v3/orgs/members/#public-members-list
+ ///
+ ///
+ IObservable GetPublic(string org);
+
+ ///
+ /// Check if a user is, publicly or privately, a member of the organization.
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ IObservable CheckMember(string org, string user);
+
+ ///
+ /// Check is a user is publicly a member of the organization.
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ IObservable CheckMemberPublic(string org, string user);
+
+ ///
+ /// Removes a user from the organization, this will also remove them from all teams
+ /// within the organization and they will no longer have any access to the organization's
+ /// repositories.
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ IObservable Delete(string org, string user);
+
+ ///
+ /// Make the authenticated user's organization membership public.
+ ///
+ ///
+ /// This method requires authentication.
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ IObservable Publicize(string org, string user);
+
+ ///
+ /// Make the authenticated user's organization membership private.
+ ///
+ ///
+ /// This method requries authentication.
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ IObservable Conceal(string org, string user);
+ }
+}
diff --git a/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs b/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs
new file mode 100644
index 00000000..2aa18de2
--- /dev/null
+++ b/Octokit.Reactive/Clients/ObservableOrganizationMembersClient.cs
@@ -0,0 +1,156 @@
+using System;
+using System.Collections.Generic;
+using System.Reactive;
+using System.Reactive.Threading.Tasks;
+using Octokit.Reactive.Internal;
+
+namespace Octokit.Reactive
+{
+ public class ObservableOrganizationMembersClient : IObservableOrganizationMembersClient
+ {
+ readonly IOrganizationMembersClient _client;
+ readonly IConnection _connection;
+
+ public ObservableOrganizationMembersClient(IGitHubClient client)
+ {
+ Ensure.ArgumentNotNull(client, "client");
+
+ _client = client.Organization.Member;
+ _connection = client.Connection;
+ }
+
+ ///
+ ///
+ /// List all users who are members of an organization. A member is a user that
+ /// belongs to at least 1 team in the organization.
+ ///
+ ///
+ /// If the authenticated user is also an owner of this organization then both
+ /// concealed and public member will be returned.
+ ///
+ ///
+ /// If the requester is not an owner of the organization the query will be redirected
+ /// to the public members list.
+ ///
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ public IObservable GetAll(string org)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.Members(org));
+ }
+
+ ///
+ /// List all users who have publicized their membership of the organization.
+ ///
+ /// http://developer.github.com/v3/orgs/members/#public-members-list
+ ///
+ ///
+ public IObservable GetPublic(string org)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+
+ return _connection.GetAndFlattenAllPages(ApiUrls.PublicMembers(org));
+ }
+
+ ///
+ /// Check if a user is, publicly or privately, a member of the organization.
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ public IObservable CheckMember(string org, string user)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+ Ensure.ArgumentNotNullOrEmptyString(user, "user");
+
+ return _client.CheckMember(org, user).ToObservable();
+ }
+
+ ///
+ /// Check is a user is publicly a member of the organization.
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ public IObservable CheckMemberPublic(string org, string user)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+ Ensure.ArgumentNotNullOrEmptyString(user, "user");
+
+ return _client.CheckMemberPublic(org, user).ToObservable();
+ }
+
+ ///
+ /// Removes a user from the organization, this will also remove them from all teams
+ /// within the organization and they will no longer have any access to the organization's
+ /// repositories.
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ public IObservable Delete(string org, string user)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+ Ensure.ArgumentNotNullOrEmptyString(user, "user");
+
+ return _client.Delete(org, user).ToObservable();
+ }
+
+ ///
+ /// Make the authenticated user's organization membership public.
+ ///
+ ///
+ /// This method requires authentication.
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ public IObservable Publicize(string org, string user)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+ Ensure.ArgumentNotNullOrEmptyString(user, "user");
+
+ return _client.Publicize(org, user).ToObservable();
+ }
+
+ ///
+ /// Make the authenticated user's organization membership private.
+ ///
+ ///
+ /// This method requries authentication.
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ ///
+ ///
+ public IObservable Conceal(string org, string user)
+ {
+ Ensure.ArgumentNotNullOrEmptyString(org, "org");
+ Ensure.ArgumentNotNullOrEmptyString(user, "user");
+
+ return _client.Conceal(org, user).ToObservable();
+ }
+ }
+}
diff --git a/Octokit.Reactive/Octokit.Reactive.csproj b/Octokit.Reactive/Octokit.Reactive.csproj
index 493f29cc..626d87f2 100644
--- a/Octokit.Reactive/Octokit.Reactive.csproj
+++ b/Octokit.Reactive/Octokit.Reactive.csproj
@@ -75,6 +75,7 @@
+
@@ -92,6 +93,7 @@
+
diff --git a/Octokit.Tests/Octokit.Tests.csproj b/Octokit.Tests/Octokit.Tests.csproj
index 6f2f5ee2..c29287f3 100644
--- a/Octokit.Tests/Octokit.Tests.csproj
+++ b/Octokit.Tests/Octokit.Tests.csproj
@@ -116,6 +116,7 @@
+
diff --git a/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs b/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs
new file mode 100644
index 00000000..9b27ea7f
--- /dev/null
+++ b/Octokit.Tests/Reactive/ObservableOrganizationMembersClientTests.cs
@@ -0,0 +1,189 @@
+using NSubstitute;
+using Octokit;
+using Octokit.Internal;
+using Octokit.Reactive;
+using Octokit.Tests.Helpers;
+using System;
+using System.Collections.Generic;
+using System.Reactive.Linq;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Octokit.Tests.Reactive
+{
+ public class ObservableOrganizationMembersClientTests
+ {
+ public class TheGetAllMethod
+ {
+ [Fact]
+ public void RequestsCorrectUrl()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.GetAll("org");
+
+ gitHubClient.Connection.GetAsync>(
+ new Uri("orgs/org/members", UriKind.Relative), null, null);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.GetAll(null));
+ await AssertEx.Throws(async () => await client.GetAll(""));
+ }
+ }
+
+ public class TheGetPublicMethod
+ {
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.GetPublic("org");
+
+ gitHubClient.Connection.GetAsync>(
+ new Uri("orgs/org/public_members", UriKind.Relative), null, null);
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.GetPublic(null));
+ await AssertEx.Throws(async () => await client.GetPublic(""));
+ }
+ }
+
+ public class TheCheckMemberMethod
+ {
+ [Fact]
+ public void ChecksMemberFromClientOrganizationMember()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.CheckMember("org", "user");
+
+ gitHubClient.Organization.Member.Received().CheckMember("org", "user");
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.CheckMember(null, "username"));
+ await AssertEx.Throws(async () => await client.CheckMember("", "username"));
+ await AssertEx.Throws(async () => await client.CheckMember("org", null));
+ await AssertEx.Throws(async () => await client.CheckMember("org", ""));
+ }
+ }
+
+ public class TheCheckMemberPublicMethod
+ {
+ [Fact]
+ public void ChecksMemberPublicFromClientOrganizationMember()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.CheckMemberPublic("org", "user");
+
+ gitHubClient.Organization.Member.Received().CheckMemberPublic("org", "user");
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.CheckMemberPublic(null, "username"));
+ await AssertEx.Throws(async () => await client.CheckMemberPublic("", "username"));
+ await AssertEx.Throws(async () => await client.CheckMemberPublic("org", null));
+ await AssertEx.Throws(async () => await client.CheckMemberPublic("org", ""));
+ }
+ }
+
+ public class TheDeleteMethod
+ {
+ [Fact]
+ public void DeletesFromClientOrganizationMember()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.Delete("org", "user");
+
+ gitHubClient.Organization.Member.Received().Delete("org", "user");
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Delete(null, "username"));
+ await AssertEx.Throws(async () => await client.Delete("", "username"));
+ await AssertEx.Throws(async () => await client.Delete("org", null));
+ await AssertEx.Throws(async () => await client.Delete("org", ""));
+ }
+ }
+
+ public class ThePublicizeMethod
+ {
+ [Fact]
+ public void PublicizeFromClientOrganizationMember()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.Publicize("org", "user");
+
+ gitHubClient.Organization.Member.Received().Publicize("org", "user");
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Publicize(null, "username"));
+ await AssertEx.Throws(async () => await client.Publicize("", "username"));
+ await AssertEx.Throws(async () => await client.Publicize("org", null));
+ await AssertEx.Throws(async () => await client.Publicize("org", ""));
+ }
+ }
+
+ public class TheConcealMethod
+ {
+ [Fact]
+ public void ConcealFromClientOrganizationMember()
+ {
+ var gitHubClient = Substitute.For();
+ var client = new ObservableOrganizationMembersClient(gitHubClient);
+
+ client.Conceal("org", "user");
+
+ gitHubClient.Organization.Member.Received().Conceal("org", "user");
+ }
+
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new ObservableOrganizationMembersClient(Substitute.For());
+
+ await AssertEx.Throws(async () => await client.Conceal(null, "username"));
+ await AssertEx.Throws(async () => await client.Conceal("", "username"));
+ await AssertEx.Throws(async () => await client.Conceal("org", null));
+ await AssertEx.Throws(async () => await client.Conceal("org", ""));
+ }
+ }
+ }
+}
diff --git a/Octokit/Clients/OrganizationMembersClient.cs b/Octokit/Clients/OrganizationMembersClient.cs
index a018008f..dcc4aa71 100644
--- a/Octokit/Clients/OrganizationMembersClient.cs
+++ b/Octokit/Clients/OrganizationMembersClient.cs
@@ -38,7 +38,7 @@ namespace Octokit
{
Ensure.ArgumentNotNullOrEmptyString(org, "org");
- return ApiConnection.GetAll("orgs/{0}/members".FormatUri(org));
+ return ApiConnection.GetAll(ApiUrls.Members(org));
}
///
@@ -51,7 +51,7 @@ namespace Octokit
{
Ensure.ArgumentNotNullOrEmptyString(org, "org");
- return ApiConnection.GetAll("orgs/{0}/public_members".FormatUri(org));
+ return ApiConnection.GetAll(ApiUrls.PublicMembers(org));
}
///
diff --git a/Octokit/Helpers/ApiUrls.cs b/Octokit/Helpers/ApiUrls.cs
index 0b4bdc61..734cddce 100644
--- a/Octokit/Helpers/ApiUrls.cs
+++ b/Octokit/Helpers/ApiUrls.cs
@@ -247,6 +247,26 @@ namespace Octokit
return "repos/{0}/{1}/assignees/{2}".FormatUri(owner, name, login);
}
+ ///
+ /// Returns the that returns all of the members of the organization
+ ///
+ /// The organization
+ ///
+ public static Uri Members(string org)
+ {
+ return "orgs/{0}/members".FormatUri(org);
+ }
+
+ ///
+ /// Returns the that returns all of the public members of the organization
+ ///
+ /// Organization
+ ///
+ public static Uri PublicMembers(string org)
+ {
+ return "orgs/{0}/public_members".FormatUri(org);
+ }
+
///
/// Returns the that returns a 204 if requester is an organization member and
/// the user is, publicly or privately a member of the organization.