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/Octokit.Tests.Integration.csproj b/Octokit.Tests.Integration/Octokit.Tests.Integration.csproj index d12eff12fd..9e3f07e736 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 @@ +