diff --git a/Octokit.Reactive/Clients/IObservableUserAdministrationClient.cs b/Octokit.Reactive/Clients/IObservableUserAdministrationClient.cs
index d893f91d8c..844a0e1598 100644
--- a/Octokit.Reactive/Clients/IObservableUserAdministrationClient.cs
+++ b/Octokit.Reactive/Clients/IObservableUserAdministrationClient.cs
@@ -5,7 +5,7 @@
namespace Octokit.Reactive
{
///
- /// A client for GitHub's User Administration API.
+ /// A client for GitHub's User Administration API (GitHub Enterprise)
///
///
/// See the Administration API documentation for more details.
@@ -13,43 +13,126 @@ namespace Octokit.Reactive
public interface IObservableUserAdministrationClient
{
///
- /// Promotes ordinary user to a site administrator.
+ /// Create a new user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#promote-an-ordinary-user-to-a-site-administrator
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The object describing the user to create
+ /// The created object
+ IObservable Create(NewUser newUser);
+
+ ///
+ /// Rename an existing user (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ /// Note that this queues a request to rename a user, rather than execute it straight away
+ ///
+ /// The username to rename
+ /// The request, specifying the new login
+ /// A object indicating the queued task message and Url to the user
+ IObservable Rename(string login, UserRename userRename);
+
+ ///
+ /// Create an impersonation OAuth token (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The user to impersonate
+ /// The request specifying the required scopes
+ /// An object containing the impersonation token
+ IObservable CreateImpersonationToken(string login, NewImpersonationToken newImpersonationToken);
+
+ ///
+ /// Deletes an impersonation OAuth token (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The user to remove impersonation token from
+ ///
+ IObservable DeleteImpersonationToken(string login);
+
+ ///
+ /// Promotes ordinary user to a site administrator (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
///
/// The user to promote to administrator.
///
IObservable Promote(string login);
///
- /// Demotes a site administrator to an ordinary user.
+ /// Demotes a site administrator to an ordinary user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#demote-a-site-administrator-to-an-ordinary-user
+ /// See the API documentation
+ /// for more information.
///
/// The user to demote from administrator.
///
IObservable Demote(string login);
///
- /// Suspends a user.
+ /// Suspends a user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#suspend-a-user
+ /// See the API documentation
+ /// for more information.
///
/// The user to suspend.
///
IObservable Suspend(string login);
///
- /// Unsuspends a user.
+ /// Unsuspends a user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#unsuspend-a-user
+ /// See the API documentation
+ /// for more information.
///
/// The user to unsuspend.
///
IObservable Unsuspend(string login);
+
+ ///
+ /// List all public keys (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ IObservable ListAllPublicKeys();
+
+ ///
+ /// Delete a user (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The user to delete
+ ///
+ IObservable Delete(string login);
+
+ ///
+ /// Delete a public key (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The key to delete
+ ///
+ IObservable DeletePublicKey(int keyId);
}
}
diff --git a/Octokit.Reactive/Clients/ObservableUserAdministrationClient.cs b/Octokit.Reactive/Clients/ObservableUserAdministrationClient.cs
index d76d7e9dad..bc0bf672e7 100644
--- a/Octokit.Reactive/Clients/ObservableUserAdministrationClient.cs
+++ b/Octokit.Reactive/Clients/ObservableUserAdministrationClient.cs
@@ -7,9 +7,16 @@
namespace Octokit.Reactive
{
+ ///
+ /// A client for GitHub's User Administration API (GitHub Enterprise)
+ ///
+ ///
+ /// See the Administration API documentation for more details.
+ ///
public class ObservableUserAdministrationClient : IObservableUserAdministrationClient
{
readonly IUserAdministrationClient _client;
+ readonly IConnection _connection;
///
/// Initializes a new instance of the class.
@@ -20,13 +27,74 @@ public ObservableUserAdministrationClient(IGitHubClient client)
Ensure.ArgumentNotNull(client, "client");
_client = client.User.Administration;
+ _connection = client.Connection;
}
///
- /// Promotes ordinary user to a site administrator.
+ /// Create a new user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#promote-an-ordinary-user-to-a-site-administrator
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The object describing the user to create
+ /// The created object
+ public IObservable Create(NewUser newUser)
+ {
+ return _client.Create(newUser).ToObservable();
+ }
+
+ ///
+ /// Rename an existing user (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ /// Note that this queues a request to rename a user, rather than execute it straight away
+ ///
+ /// The username to rename
+ /// The request, specifying the new login
+ /// A object indicating the queued task message and Url to the user
+ public IObservable Rename(string login, UserRename userRename)
+ {
+ return _client.Rename(login, userRename).ToObservable();
+ }
+
+ ///
+ /// Create an impersonation OAuth token (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The user to impersonate
+ /// The request specifying the required scopes
+ /// An object containing the impersonation token
+ public IObservable CreateImpersonationToken(string login, NewImpersonationToken newImpersonationToken)
+ {
+ return _client.CreateImpersonationToken(login, newImpersonationToken).ToObservable();
+ }
+
+ ///
+ /// Deletes an impersonation OAuth token (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The user to remove impersonation token from
+ ///
+ public IObservable DeleteImpersonationToken(string login)
+ {
+ return _client.DeleteImpersonationToken(login).ToObservable();
+ }
+
+ ///
+ /// Promotes ordinary user to a site administrator (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
///
/// The user to promote to administrator.
///
@@ -36,10 +104,11 @@ public IObservable Promote(string login)
}
///
- /// Demotes a site administrator to an ordinary user.
+ /// Demotes a site administrator to an ordinary user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#demote-a-site-administrator-to-an-ordinary-user
+ /// See the API documentation
+ /// for more information.
///
/// The user to demote from administrator.
///
@@ -49,10 +118,11 @@ public IObservable Demote(string login)
}
///
- /// Suspends a user.
+ /// Suspends a user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#suspend-a-user
+ /// See the API documentation
+ /// for more information.
///
/// The user to suspend.
///
@@ -62,10 +132,11 @@ public IObservable Suspend(string login)
}
///
- /// Unsuspends a user.
+ /// Unsuspends a user (must be Site Admin user).
///
///
- /// https://developer.github.com/v3/users/administration/#unsuspend-a-user
+ /// See the API documentation
+ /// for more information.
///
/// The user to unsuspend.
///
@@ -73,5 +144,46 @@ public IObservable Unsuspend(string login)
{
return _client.Unsuspend(login).ToObservable();
}
+
+ ///
+ /// List all public keys (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ ///
+ public IObservable ListAllPublicKeys()
+ {
+ return _connection.GetAndFlattenAllPages(ApiUrls.UserAdministrationPublicKeys());
+ }
+
+ ///
+ /// Delete a user (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The user to delete
+ ///
+ public IObservable Delete(string login)
+ {
+ return _client.Delete(login).ToObservable();
+ }
+
+ ///
+ /// Delete a public key (must be Site Admin user).
+ ///
+ ///
+ /// See the API documentation
+ /// for more information.
+ ///
+ /// The key to delete
+ ///
+ public IObservable DeletePublicKey(int keyId)
+ {
+ return _client.DeletePublicKey(keyId).ToObservable();
+ }
}
}
diff --git a/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs b/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs
new file mode 100644
index 0000000000..321017ac3d
--- /dev/null
+++ b/Octokit.Tests.Integration/Clients/UserAdministrationClientTests.cs
@@ -0,0 +1,196 @@
+using System;
+using System.Linq;
+using System.Threading.Tasks;
+using Octokit.Tests.Integration.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Integration.Clients
+{
+ public class UserAdministrationClientTests
+ {
+ readonly IGitHubClient _github;
+
+ public UserAdministrationClientTests()
+ {
+ _github = EnterpriseHelper.GetAuthenticatedClient();
+ }
+
+ private NewUser GenerateNewUserDetails()
+ {
+ string username = Helper.MakeNameWithTimestamp("user");
+ string email = string.Concat(username, "@company.com");
+ return new NewUser(username, email);
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanCreateAndDelete()
+ {
+ User checkUser = null;
+
+ // Create a new user
+ var newUser = GenerateNewUserDetails();
+
+ var user = await
+ _github.User.Administration.Create(newUser);
+
+ // Check returned object (cant check email as it isn't public)
+ Assert.NotNull(user);
+ Assert.Equal(user.Login, newUser.Login);
+
+ // Get user to check they exist
+ checkUser = await _github.User.Get(newUser.Login);
+ Assert.Equal(checkUser.Login, newUser.Login);
+
+ // Delete the user
+ await _github.User.Administration.Delete(newUser.Login);
+
+ // Ensure user doesnt exist
+ try
+ {
+ checkUser = await _github.User.Get(newUser.Login);
+ if (checkUser != null)
+ {
+ throw new Exception("User still exists!");
+ }
+ }
+ catch (ApiException e)
+ {
+ if (e.StatusCode != System.Net.HttpStatusCode.NotFound)
+ {
+ throw;
+ }
+ }
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanRename()
+ {
+ string renamedUsername = Helper.MakeNameWithTimestamp("user-renamed");
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ var response = await _github.User.Administration.Rename(
+ context.UserLogin,
+ new UserRename(renamedUsername));
+
+ Assert.NotNull(response);
+ Assert.StartsWith("Job queued to rename user", response.Message);
+ Assert.EndsWith(context.UserId.ToString(), response.Url);
+ }
+
+ // Remove user if it was already renamed
+ EnterpriseHelper.DeleteUser(renamedUsername);
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanAddAndDeleteImpersonationToken()
+ {
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Create Impersonation token
+ var token = await _github.User.Administration.CreateImpersonationToken(
+ context.UserLogin,
+ new NewImpersonationToken(new string[] { "public_repo" }));
+
+ Assert.NotNull(token);
+ Assert.True(
+ token.Scopes.Count() == 1 &&
+ token.Scopes.All(s => s == "public_repo"));
+
+ // Delete Impersonation token
+ await _github.User.Administration.DeleteImpersonationToken(context.UserLogin);
+ }
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanPromoteAndDemote()
+ {
+ User checkUser = null;
+
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user is not site admin
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.SiteAdmin);
+
+ // Promote to site admin
+ await _github.User.Administration.Promote(context.UserLogin);
+
+ // Ensure user is site admin
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.True(checkUser.SiteAdmin);
+
+ // Demote user
+ await _github.User.Administration.Demote(context.UserLogin);
+
+ // Ensure user is not site admin
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.SiteAdmin);
+ }
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanSuspendAndUnsuspend()
+ {
+ User checkUser = null;
+
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user is not suspended
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.Suspended);
+
+ // Suspend user
+ await _github.User.Administration.Suspend(context.UserLogin);
+
+ // Ensure user is suspended
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.True(checkUser.Suspended);
+
+ // Unsuspend user
+ await _github.User.Administration.Unsuspend(context.UserLogin);
+
+ // Ensure user is not suspended
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.Suspended);
+ }
+ }
+
+ [GitHubEnterpriseTest(Skip = "Currently no way to add keys, so cant test listing keys")]
+ public async Task CanListAllPublicKeys()
+ {
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user has a key
+ //var key = await _github.User.Keys.Create(new NewPublicKey("title", "key"));
+
+ // Get public keys
+ var keys = await _github.User.Administration.ListAllPublicKeys();
+
+ Assert.NotNull(keys);
+ Assert.True(keys.Count > 0);
+
+ // Delete key
+ //await _github.User.Administration.DeletePublicKey(key.Id);
+ }
+ }
+
+ [GitHubEnterpriseTest(Skip = "Currently no way to add keys, so cant test deleting keys")]
+ public async Task CanDeletePublicKey()
+ {
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user has a key
+ //var key = await _github.User.Keys.Create(new NewPublicKey("title", "key"));
+
+ // Delete key
+ //await _github.User.Administration.DeletePublicKey(key.Id);
+ }
+ }
+ }
+}
diff --git a/Octokit.Tests.Integration/EnterpriseHelper.cs b/Octokit.Tests.Integration/EnterpriseHelper.cs
index 63323012cc..7e03a604a2 100644
--- a/Octokit.Tests.Integration/EnterpriseHelper.cs
+++ b/Octokit.Tests.Integration/EnterpriseHelper.cs
@@ -140,6 +140,22 @@ public static void DeleteTeam(int teamId)
catch { }
}
+ public static void DeleteUser(User user)
+ {
+ if (user != null)
+ DeleteUser(user.Login);
+ }
+
+ public static void DeleteUser(string username)
+ {
+ var api = GetAuthenticatedClient();
+ try
+ {
+ api.User.Administration.Delete(username).Wait(TimeSpan.FromSeconds(15));
+ }
+ catch { }
+ }
+
public static IGitHubClient GetAuthenticatedClient()
{
return new GitHubClient(new ProductHeaderValue("OctokitEnterpriseTests"), GitHubEnterpriseUrl)
diff --git a/Octokit.Tests.Integration/Helpers/EnterpriseUserContext.cs b/Octokit.Tests.Integration/Helpers/EnterpriseUserContext.cs
new file mode 100644
index 0000000000..496fb52d3c
--- /dev/null
+++ b/Octokit.Tests.Integration/Helpers/EnterpriseUserContext.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Octokit.Tests.Integration.Helpers
+{
+ internal sealed class EnterpriseUserContext : IDisposable
+ {
+ internal EnterpriseUserContext(User user)
+ {
+ User = user;
+ UserId = user.Id;
+ UserLogin = user.Login;
+ UserEmail = user.Email;
+ }
+
+ internal int UserId { get; private set; }
+ internal string UserLogin { get; private set; }
+ internal string UserEmail { get; private set; }
+
+ internal User User { get; private set; }
+
+ public void Dispose()
+ {
+ EnterpriseHelper.DeleteUser(User);
+ }
+ }
+}
diff --git a/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs
index badd2b5623..e262aba0b6 100644
--- a/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs
+++ b/Octokit.Tests.Integration/Helpers/GithubClientExtensions.cs
@@ -36,5 +36,12 @@ internal async static Task CreateEnterpriseTeamContext(th
return new EnterpriseTeamContext(team);
}
+
+ internal async static Task CreateEnterpriseUserContext(this IGitHubClient client, NewUser newUser)
+ {
+ var user = await client.User.Administration.Create(newUser);
+
+ return new EnterpriseUserContext(user);
+ }
}
}
\ No newline at end of file
diff --git a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
index 8a5919ade6..030795b0d0 100644
--- a/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
+++ b/Octokit.Tests.Integration/Helpers/ObservableGithubClientExtensions.cs
@@ -27,5 +27,19 @@ internal async static Task CreateRepositoryContext(this IObse
return new RepositoryContext(repo);
}
+
+ internal async static Task CreateEnterpriseTeamContext(this IObservableGitHubClient client, string organization, NewTeam newTeam)
+ {
+ var team = await client.Organization.Team.Create(organization, newTeam);
+
+ return new EnterpriseTeamContext(team);
+ }
+
+ internal async static Task CreateEnterpriseUserContext(this IObservableGitHubClient client, NewUser newUser)
+ {
+ var user = await client.User.Administration.Create(newUser);
+
+ return new EnterpriseUserContext(user);
+ }
}
}
\ No newline at end of file
diff --git a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
index d12eff12fd..3900738aca 100644
--- a/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
+++ b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj
@@ -105,6 +105,7 @@
+
@@ -112,6 +113,7 @@
+
@@ -143,6 +145,7 @@
+
diff --git a/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs b/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs
index 0880616259..dde932d8c9 100644
--- a/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs
+++ b/Octokit.Tests.Integration/Reactive/Enterprise/ObservableEnterpriseLdapClientTests.cs
@@ -20,11 +20,10 @@ public class ObservableEnterpriseLdapClientTests : IDisposable
public ObservableEnterpriseLdapClientTests()
{
- var gitHub = EnterpriseHelper.GetAuthenticatedClient();
- _github = new ObservableGitHubClient(gitHub);
+ _github = new ObservableGitHubClient(EnterpriseHelper.GetAuthenticatedClient());
NewTeam newTeam = new NewTeam(Helper.MakeNameWithTimestamp("test-team")) { Description = "Test Team" };
- _context = gitHub.CreateEnterpriseTeamContext(EnterpriseHelper.Organization, newTeam).Result;
+ _context = _github.CreateEnterpriseTeamContext(EnterpriseHelper.Organization, newTeam).Result;
}
[GitHubEnterpriseTest]
diff --git a/Octokit.Tests.Integration/Reactive/ObservableUserAdministrationClientTests.cs b/Octokit.Tests.Integration/Reactive/ObservableUserAdministrationClientTests.cs
new file mode 100644
index 0000000000..efaea9a0bd
--- /dev/null
+++ b/Octokit.Tests.Integration/Reactive/ObservableUserAdministrationClientTests.cs
@@ -0,0 +1,201 @@
+using System;
+using System.Linq;
+using System.Reactive.Linq;
+using System.Threading.Tasks;
+using Octokit.Reactive;
+using Octokit.Tests.Integration.Helpers;
+using Xunit;
+
+namespace Octokit.Tests.Integration.Clients
+{
+ public class ObservableUserAdministrationClientTests
+ {
+ readonly IObservableGitHubClient _github;
+
+ public ObservableUserAdministrationClientTests()
+ {
+ _github = new ObservableGitHubClient(EnterpriseHelper.GetAuthenticatedClient());
+ }
+
+ private NewUser GenerateNewUserDetails()
+ {
+ string username = Helper.MakeNameWithTimestamp("user");
+ string email = string.Concat(username, "@company.com");
+ return new NewUser(username, email);
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanCreateAndDelete()
+ {
+ User checkUser = null;
+
+ // Create a new user
+ var newUser = GenerateNewUserDetails();
+
+ var observable = _github.User.Administration.Create(newUser);
+ var user = await observable;
+
+ // Check returned object (cant check email as it isn't public)
+ Assert.NotNull(user);
+ Assert.Equal(user.Login, newUser.Login);
+
+ // Get user to check they exist
+ checkUser = await _github.User.Get(newUser.Login);
+ Assert.Equal(checkUser.Login, newUser.Login);
+
+ // Delete the user
+ await _github.User.Administration.Delete(newUser.Login);
+
+ // Ensure user doesnt exist
+ try
+ {
+ checkUser = await _github.User.Get(newUser.Login);
+ if (checkUser != null)
+ {
+ throw new Exception("User still exists!");
+ }
+ }
+ catch (ApiException e)
+ {
+ if (e.StatusCode != System.Net.HttpStatusCode.NotFound)
+ {
+ throw;
+ }
+ }
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanRename()
+ {
+ string renamedUsername = Helper.MakeNameWithTimestamp("user-renamed");
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ var observable = _github.User.Administration.Rename(
+ context.UserLogin,
+ new UserRename(renamedUsername));
+ var response = await observable;
+
+ Assert.NotNull(response);
+ Assert.StartsWith("Job queued to rename user", response.Message);
+ Assert.EndsWith(context.UserId.ToString(), response.Url);
+ }
+
+ // Remove user if it was already renamed
+ EnterpriseHelper.DeleteUser(renamedUsername);
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanAddAndDeleteImpersonationToken()
+ {
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Create Impersonation token
+ var observable = _github.User.Administration.CreateImpersonationToken(
+ context.UserLogin,
+ new NewImpersonationToken(new string[] { "public_repo" }));
+ var token = await observable;
+
+ Assert.NotNull(token);
+ Assert.True(
+ token.Scopes.Count() == 1 &&
+ token.Scopes.All(s => s == "public_repo"));
+
+ // Delete Impersonation token
+ await _github.User.Administration.DeleteImpersonationToken(context.UserLogin);
+ }
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanPromoteAndDemote()
+ {
+ User checkUser = null;
+
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user is not site admin
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.SiteAdmin);
+
+ // Promote to site admin
+ await _github.User.Administration.Promote(context.UserLogin);
+
+ // Ensure user is site admin
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.True(checkUser.SiteAdmin);
+
+ // Demote user
+ await _github.User.Administration.Demote(context.UserLogin);
+
+ // Ensure user is not site admin
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.SiteAdmin);
+ }
+ }
+
+ [GitHubEnterpriseTest]
+ public async Task CanSuspendAndUnsuspend()
+ {
+ User checkUser = null;
+
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user is not suspended
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.Suspended);
+
+ // Suspend user
+ await _github.User.Administration.Suspend(context.UserLogin);
+
+ // Ensure user is suspended
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.True(checkUser.Suspended);
+
+ // Unsuspend user
+ await _github.User.Administration.Unsuspend(context.UserLogin);
+
+ // Ensure user is not suspended
+ checkUser = await _github.User.Get(context.UserLogin);
+ Assert.False(checkUser.Suspended);
+ }
+ }
+
+ [GitHubEnterpriseTest(Skip = "Currently no way to add keys, so cant test listing keys")]
+ public async Task CanListAllPublicKeys()
+ {
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user has a key
+ //var key = await _github.User.Keys.Create(new NewPublicKey("title", "key"));
+
+ // Get public keys
+ var observable = _github.User.Administration.ListAllPublicKeys();
+ var keys = await (observable.ToList());
+
+ Assert.NotNull(keys);
+ Assert.True(keys.Count > 0);
+
+ // Delete key
+ //await _github.User.Administration.DeletePublicKey(key.Id);
+ }
+ }
+
+ [GitHubEnterpriseTest(Skip = "Currently no way to add keys, so cant test deleting keys")]
+ public async Task CanDeletePublicKey()
+ {
+ // Create a disposable user for the test
+ using (var context = _github.CreateEnterpriseUserContext(GenerateNewUserDetails()).Result)
+ {
+ // Ensure user has a key
+ //var key = await _github.User.Keys.Create(new NewPublicKey("title", "key"));
+
+ // Delete key
+ //await _github.User.Administration.DeletePublicKey(key.Id);
+ }
+ }
+ }
+}
diff --git a/Octokit.Tests/Clients/UserAdministrationClientTests.cs b/Octokit.Tests/Clients/UserAdministrationClientTests.cs
index 573fe10793..4174b06be5 100644
--- a/Octokit.Tests/Clients/UserAdministrationClientTests.cs
+++ b/Octokit.Tests/Clients/UserAdministrationClientTests.cs
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
+using System.Linq;
using System.Threading.Tasks;
using NSubstitute;
using Octokit.Tests.Helpers;
@@ -9,6 +10,174 @@ namespace Octokit.Tests.Clients
{
public class UserAdministrationClientTests
{
+ public class TheCreateMethod
+ {
+ [Fact]
+ public async Task EnsuresNonNullArguments()
+ {
+ var client = new UserAdministrationClient(Substitute.For());
+ await Assert.ThrowsAsync(() => client.Create(null));
+ }
+
+ [Fact]
+ public void RequestsTheCorrectUrl()
+ {
+ var connection = Substitute.For();
+ var client = new UserAdministrationClient(connection);
+
+ var expectedUri = "admin/users";
+ client.Create(new NewUser("name", "email@company.com"));
+
+ connection.Received().Post(
+ Arg.Is(u => u.ToString() == expectedUri),
+ Arg.Any