mirror of
https://github.com/tgstation/tgstation-server.git
synced 2026-07-21 13:03:41 +01:00
730 lines
28 KiB
C#
730 lines
28 KiB
C#
using Elastic.CommonSchema;
|
|
|
|
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
|
|
|
using StrawberryShake;
|
|
|
|
using System;
|
|
using System.Collections.Concurrent;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
using Tgstation.Server.Api.Models;
|
|
using Tgstation.Server.Api.Models.Request;
|
|
using Tgstation.Server.Api.Models.Response;
|
|
using Tgstation.Server.Api.Rights;
|
|
using Tgstation.Server.Client;
|
|
using Tgstation.Server.Client.GraphQL;
|
|
using Tgstation.Server.Common.Extensions;
|
|
using Tgstation.Server.Host.Controllers;
|
|
using Tgstation.Server.Host.System;
|
|
|
|
namespace Tgstation.Server.Tests.Live
|
|
{
|
|
sealed class UsersTest
|
|
{
|
|
readonly IMultiServerClient serverClient;
|
|
|
|
public UsersTest(IMultiServerClient serverClient)
|
|
{
|
|
this.serverClient = serverClient ?? throw new ArgumentNullException(nameof(serverClient));
|
|
}
|
|
|
|
public async ValueTask Run(CancellationToken cancellationToken)
|
|
{
|
|
var observer = new HoldLastObserver<IOperationResult<ISubscribeUsersResult>>();
|
|
using var subscription = await serverClient.Subscribe(
|
|
gql => gql.SubscribeUsers.Watch(),
|
|
observer,
|
|
cancellationToken);
|
|
|
|
await BasicTests(cancellationToken);
|
|
|
|
await ValueTaskExtensions.WhenAll(
|
|
TestCreateSysUser(cancellationToken),
|
|
TestSpamCreation(cancellationToken));
|
|
|
|
await TestPagination(cancellationToken);
|
|
|
|
if (!MultiServerClient.UseGraphQL)
|
|
return;
|
|
|
|
Assert.IsFalse(observer.Completed);
|
|
Assert.AreEqual(0U, observer.ErrorCount);
|
|
|
|
var expected = new PlatformIdentifier().IsWindows ? 108U : 107U;
|
|
// wait up to 10s
|
|
var lastSeen = observer.ResultCount;
|
|
for (var i = 0; i < 10 && observer.ResultCount < expected; ++i)
|
|
{
|
|
await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken);
|
|
if (observer.ResultCount > lastSeen)
|
|
{
|
|
lastSeen = observer.ResultCount;
|
|
i = -1;
|
|
}
|
|
}
|
|
|
|
Assert.AreEqual(expected, observer.ResultCount); // sys user
|
|
observer.LastValue.EnsureNoErrors();
|
|
}
|
|
|
|
async ValueTask BasicTests(CancellationToken cancellationToken)
|
|
{
|
|
var (restUser, gqlUser) = await serverClient.ExecuteReadOnlyConfirmEquivalence(
|
|
client => client.Users.Read(cancellationToken),
|
|
client => client.ReadCurrentUser.ExecuteAsync(cancellationToken),
|
|
(restResult, graphQLResult) =>
|
|
{
|
|
var gqlUser = graphQLResult.Swarm.Users.Current;
|
|
return restResult.Enabled == gqlUser.Enabled
|
|
&& restResult.Name == gqlUser.Name
|
|
&& (restResult.CreatedAt.Value.Ticks / 10000) == (gqlUser.CreatedAt.Ticks / 10000)
|
|
&& restResult.SystemIdentifier == gqlUser.SystemIdentifier
|
|
&& restResult.CreatedBy.Name == gqlUser.CreatedBy.Name;
|
|
},
|
|
cancellationToken);
|
|
|
|
Assert.IsNotNull(restUser);
|
|
Assert.AreEqual("Admin", restUser.Name);
|
|
Assert.IsNull(restUser.SystemIdentifier);
|
|
Assert.AreEqual(true, restUser.Enabled);
|
|
Assert.IsNotNull(restUser.OAuthConnections);
|
|
Assert.IsNotNull(restUser.PermissionSet);
|
|
Assert.IsNotNull(restUser.PermissionSet.Id);
|
|
Assert.IsNotNull(restUser.PermissionSet.InstanceManagerRights);
|
|
Assert.IsNotNull(restUser.PermissionSet.AdministrationRights);
|
|
|
|
var systemUser = restUser.CreatedBy;
|
|
Assert.IsNotNull(systemUser);
|
|
Assert.AreEqual("TGS", systemUser.Name);
|
|
|
|
await serverClient.Execute(
|
|
async client =>
|
|
{
|
|
var users = await client.Users.List(null, cancellationToken);
|
|
Assert.IsTrue(users.Count > 0);
|
|
Assert.IsFalse(users.Any(x => x.Id == systemUser.Id));
|
|
|
|
await ApiAssert.ThrowsExactly<InsufficientPermissionsException, UserResponse>(() => client.Users.GetId(systemUser, cancellationToken));
|
|
await ApiAssert.ThrowsExactly<InsufficientPermissionsException, UserResponse>(() => client.Users.Update(new UserUpdateRequest
|
|
{
|
|
Id = systemUser.Id
|
|
}, cancellationToken));
|
|
|
|
var sampleOAuthConnections = new List<OAuthConnection>
|
|
{
|
|
new()
|
|
{
|
|
ExternalUserId = "asdfasdf",
|
|
Provider = Api.Models.OAuthProvider.Discord
|
|
}
|
|
};
|
|
|
|
await ApiAssert.ThrowsExactly<ApiConflictException, UserResponse>(() => client.Users.Update(new UserUpdateRequest
|
|
{
|
|
Id = restUser.Id,
|
|
OAuthConnections = sampleOAuthConnections
|
|
}, cancellationToken), Api.Models.ErrorCode.AdminUserCannotHaveServiceConnection);
|
|
|
|
var testUser = await client.Users.Create(
|
|
new UserCreateRequest
|
|
{
|
|
Name = $"BasicTestUser",
|
|
Password = "asdfasdjfhauwiehruiy273894234jhndjkwh"
|
|
},
|
|
cancellationToken);
|
|
|
|
Assert.IsNotNull(testUser.OAuthConnections);
|
|
testUser = await client.Users.Update(
|
|
new UserUpdateRequest
|
|
{
|
|
Id = testUser.Id,
|
|
OAuthConnections = sampleOAuthConnections
|
|
},
|
|
cancellationToken);
|
|
|
|
Assert.AreEqual(1, testUser.OAuthConnections.Count);
|
|
Assert.AreEqual(sampleOAuthConnections.First().ExternalUserId, testUser.OAuthConnections.First().ExternalUserId);
|
|
Assert.AreEqual(sampleOAuthConnections.First().Provider, testUser.OAuthConnections.First().Provider);
|
|
|
|
var group = await client.Groups.Create(
|
|
new UserGroupCreateRequest
|
|
{
|
|
Name = "TestGroup"
|
|
},
|
|
cancellationToken);
|
|
Assert.AreEqual(group.Name, "TestGroup");
|
|
Assert.IsNotNull(group.PermissionSet);
|
|
Assert.IsNotNull(group.PermissionSet.Id);
|
|
Assert.AreEqual(AdministrationRights.None, group.PermissionSet.AdministrationRights);
|
|
Assert.AreEqual(InstanceManagerRights.None, group.PermissionSet.InstanceManagerRights);
|
|
|
|
var group2 = await client.Groups.Create(new UserGroupCreateRequest
|
|
{
|
|
Name = "TestGroup2",
|
|
PermissionSet = new PermissionSet
|
|
{
|
|
InstanceManagerRights = InstanceManagerRights.List
|
|
}
|
|
}, cancellationToken);
|
|
Assert.AreEqual(AdministrationRights.None, group2.PermissionSet.AdministrationRights);
|
|
Assert.AreEqual(InstanceManagerRights.List, group2.PermissionSet.InstanceManagerRights);
|
|
|
|
var groups = await client.Groups.List(null, cancellationToken);
|
|
Assert.AreEqual(2, groups.Count);
|
|
|
|
foreach (var igroup in groups)
|
|
{
|
|
Assert.IsNotNull(igroup.Users);
|
|
Assert.IsNotNull(igroup.PermissionSet);
|
|
}
|
|
|
|
await client.Groups.Delete(group2, cancellationToken);
|
|
|
|
groups = await client.Groups.List(null, cancellationToken);
|
|
Assert.AreEqual(1, groups.Count);
|
|
|
|
group = await client.Groups.Update(new UserGroupUpdateRequest
|
|
{
|
|
Id = groups[0].Id,
|
|
PermissionSet = new PermissionSet
|
|
{
|
|
InstanceManagerRights = RightsHelper.AllRights<InstanceManagerRights>(),
|
|
AdministrationRights = RightsHelper.AllRights<AdministrationRights>(),
|
|
}
|
|
}, cancellationToken);
|
|
|
|
Assert.AreEqual(RightsHelper.AllRights<AdministrationRights>(), group.PermissionSet.AdministrationRights);
|
|
Assert.AreEqual(RightsHelper.AllRights<InstanceManagerRights>(), group.PermissionSet.InstanceManagerRights);
|
|
|
|
UserUpdateRequest testUserUpdate = new UserCreateRequest
|
|
{
|
|
Name = "TestUserWithNoPassword",
|
|
Password = string.Empty
|
|
};
|
|
|
|
await ApiAssert.ThrowsExactly<ApiConflictException, UserResponse>(() => client.Users.Create((UserCreateRequest)testUserUpdate, cancellationToken), Api.Models.ErrorCode.UserPasswordLength);
|
|
|
|
testUserUpdate.OAuthConnections =
|
|
[
|
|
new()
|
|
{
|
|
ExternalUserId = "asdf",
|
|
Provider = Api.Models.OAuthProvider.GitHub
|
|
}
|
|
];
|
|
|
|
var testUser2 = await client.Users.Create((UserCreateRequest)testUserUpdate, cancellationToken);
|
|
|
|
testUserUpdate = new UserUpdateRequest
|
|
{
|
|
Id = testUser2.Id,
|
|
PermissionSet = testUser2.PermissionSet,
|
|
Group = new Api.Models.Internal.UserGroup
|
|
{
|
|
Id = group.Id
|
|
},
|
|
};
|
|
await ApiAssert.ThrowsExactly<ApiConflictException, UserResponse>(
|
|
() => client.Users.Update(
|
|
testUserUpdate,
|
|
cancellationToken),
|
|
Api.Models.ErrorCode.UserGroupAndPermissionSet);
|
|
|
|
testUserUpdate.PermissionSet = null;
|
|
|
|
testUser2 = await client.Users.Update(testUserUpdate, cancellationToken);
|
|
|
|
Assert.IsNull(testUser2.PermissionSet);
|
|
Assert.IsNotNull(testUser2.Group);
|
|
Assert.AreEqual(group.Id, testUser2.Group.Id);
|
|
|
|
var group4 = await client.Groups.GetId(group, cancellationToken);
|
|
Assert.IsNotNull(group4.Users);
|
|
Assert.AreEqual(1, group4.Users.Count);
|
|
Assert.AreEqual(testUser2.Id, group4.Users.First().Id);
|
|
Assert.IsNotNull(group4.PermissionSet);
|
|
|
|
testUserUpdate.Group = null;
|
|
testUserUpdate.PermissionSet = new PermissionSet
|
|
{
|
|
AdministrationRights = RightsHelper.AllRights<AdministrationRights>(),
|
|
InstanceManagerRights = RightsHelper.AllRights<InstanceManagerRights>(),
|
|
};
|
|
|
|
testUser2 = await client.Users.Update(testUserUpdate, cancellationToken);
|
|
Assert.IsNull(testUser2.Group);
|
|
Assert.IsNotNull(testUser2.PermissionSet);
|
|
},
|
|
async client =>
|
|
{
|
|
var result = await client.RunOperation(gql => gql.ListUsers.ExecuteAsync(cancellationToken), cancellationToken);
|
|
result.EnsureNoErrors();
|
|
var users = result.Data.Swarm.Users.QueryableUsers;
|
|
Assert.IsTrue(users.Nodes.Count > 0);
|
|
// Can't assert this, there's a race condition
|
|
// Assert.AreEqual(Math.Min(ApiController.DefaultPageSize, users.TotalCount), users.Nodes.Count);
|
|
Assert.IsTrue(Math.Min(ApiController.DefaultPageSize, users.TotalCount) >= users.Nodes.Count);
|
|
|
|
var tgsUserResult = await client.RunOperation(gql => gql.GetUserNameByNodeId.ExecuteAsync(gqlUser.Swarm.Users.Current.CreatedBy.Id, cancellationToken), cancellationToken);
|
|
tgsUserResult.EnsureNoErrors();
|
|
var tgsUserResult2 = await client.RunOperation(gql => gql.GetUserById.ExecuteAsync(gqlUser.Swarm.Users.Current.CreatedBy.Id, cancellationToken), cancellationToken);
|
|
Assert.IsTrue(tgsUserResult2.IsErrorResult());
|
|
|
|
var sampleOAuthConnections = new List<OAuthConnectionInput>
|
|
{
|
|
new()
|
|
{
|
|
ExternalUserId = "asdfasdf",
|
|
Provider = Client.GraphQL.OAuthProvider.Discord,
|
|
}
|
|
};
|
|
|
|
await ApiAssert.OperationFails(
|
|
client,
|
|
gql => gql.SetUserOAuthConnections.ExecuteAsync(
|
|
gqlUser.Swarm.Users.Current.Id,
|
|
sampleOAuthConnections,
|
|
cancellationToken),
|
|
data => data.UpdateUser,
|
|
Client.GraphQL.ErrorCode.AdminUserCannotHaveServiceConnection,
|
|
cancellationToken);
|
|
|
|
var testUserResult = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.CreateUserWithPasswordSelectOAuthConnections.ExecuteAsync("BasicTestUser", "asdfasdjfhauwiehruiy273894234jhndjkwh", cancellationToken),
|
|
data => data.CreateUserByPasswordAndPermissionSet,
|
|
cancellationToken);
|
|
|
|
var testUserResult2 = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.UpdateUserOAuthConnections.ExecuteAsync(
|
|
testUserResult.UpdatedUser.Id,
|
|
sampleOAuthConnections,
|
|
cancellationToken),
|
|
data => data.UpdateUser,
|
|
cancellationToken);
|
|
|
|
var testUser = testUserResult2.UpdatedUser.User;
|
|
Assert.IsNotNull(testUser.OAuthConnections);
|
|
Assert.AreEqual(1, testUser.OAuthConnections.Count);
|
|
Assert.AreEqual(sampleOAuthConnections.First().ExternalUserId, testUser.OAuthConnections[0].ExternalUserId);
|
|
Assert.AreEqual(sampleOAuthConnections.First().Provider, testUser.OAuthConnections[0].Provider);
|
|
|
|
var groupResult = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.CreateUserGroup.ExecuteAsync("TestGroup", cancellationToken),
|
|
data => data.CreateUserGroup,
|
|
cancellationToken);
|
|
|
|
var group = groupResult.UserGroup;
|
|
Assert.AreEqual(group.Name, "TestGroup");
|
|
Assert.IsNotNull(group.PermissionSet);
|
|
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanSetOnline);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanRelocate);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanRename);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanSetConfiguration);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanRead);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanCreate);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanDelete);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanGrantPermissions);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanList);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanSetAutoUpdate);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanSetChatBotLimit);
|
|
Assert.IsFalse(group.PermissionSet.InstanceManagerRights.CanSetConfiguration);
|
|
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanChangeVersion);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanDownloadLogs);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanEditOwnServiceConnections);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanEditOwnPassword);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanReadUsers);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanRestartHost);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanUploadVersion);
|
|
Assert.IsFalse(group.PermissionSet.AdministrationRights.CanWriteUsers);
|
|
|
|
var group2Result = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.CreateUserGroupWithInstanceListPerm.ExecuteAsync("TestGroup2", cancellationToken),
|
|
data => data.CreateUserGroup,
|
|
cancellationToken);
|
|
|
|
var group2 = group2Result.UserGroup;
|
|
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanSetOnline);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanRelocate);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanRename);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanSetConfiguration);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanRead);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanCreate);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanDelete);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanGrantPermissions);
|
|
Assert.IsTrue(group2.PermissionSet.InstanceManagerRights.CanList);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanSetAutoUpdate);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanSetChatBotLimit);
|
|
Assert.IsFalse(group2.PermissionSet.InstanceManagerRights.CanSetConfiguration);
|
|
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanChangeVersion);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanDownloadLogs);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanEditOwnServiceConnections);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanEditOwnPassword);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanReadUsers);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanRestartHost);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanUploadVersion);
|
|
Assert.IsFalse(group2.PermissionSet.AdministrationRights.CanWriteUsers);
|
|
|
|
var groupsResult = await client.RunQueryEnsureNoErrors(
|
|
gql => gql.ListUserGroups.ExecuteAsync(cancellationToken),
|
|
cancellationToken);
|
|
|
|
var groups = groupsResult.Swarm.UserGroups.QueryableGroups;
|
|
Assert.AreEqual(2, groups.TotalCount);
|
|
|
|
foreach (var igroup in groups.Nodes)
|
|
Assert.IsNotNull(igroup.Id);
|
|
|
|
var deleteResult = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.DeleteUserGroup.ExecuteAsync(group2.Id, cancellationToken),
|
|
data => data.DeleteEmptyUserGroup,
|
|
cancellationToken);
|
|
|
|
groupsResult = await client.RunQueryEnsureNoErrors(
|
|
gql => gql.ListUserGroups.ExecuteAsync(cancellationToken),
|
|
cancellationToken);
|
|
|
|
groups = groupsResult.Swarm.UserGroups.QueryableGroups;
|
|
Assert.AreEqual(1, groups.TotalCount);
|
|
|
|
foreach (var igroup in groups.Nodes)
|
|
Assert.IsNotNull(igroup.Id);
|
|
|
|
var group3Result = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.SetFullPermsOnUserGroup.ExecuteAsync(group.Id, cancellationToken),
|
|
data => data.UpdateUserGroup,
|
|
cancellationToken);
|
|
|
|
var group3 = group3Result.UserGroup;
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanSetOnline);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanRelocate);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanRename);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanSetConfiguration);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanRead);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanCreate);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanDelete);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanGrantPermissions);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanList);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanSetAutoUpdate);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanSetChatBotLimit);
|
|
Assert.IsTrue(group3.PermissionSet.InstanceManagerRights.CanSetConfiguration);
|
|
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanChangeVersion);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanDownloadLogs);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanEditOwnServiceConnections);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanEditOwnPassword);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanReadUsers);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanRestartHost);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanUploadVersion);
|
|
Assert.IsTrue(group3.PermissionSet.AdministrationRights.CanWriteUsers);
|
|
|
|
await ApiAssert.OperationFails(
|
|
client,
|
|
gql => gql.CreateUserWithPassword.ExecuteAsync("TestUserWithNoPassword", String.Empty, cancellationToken),
|
|
data => data.CreateUserByPasswordAndPermissionSet,
|
|
Client.GraphQL.ErrorCode.ModelValidationFailure,
|
|
cancellationToken);
|
|
|
|
await ApiAssert.OperationFails(
|
|
client,
|
|
gql => gql.CreateUserWithPassword.ExecuteAsync("TestUserWithShortPassword", "a", cancellationToken),
|
|
data => data.CreateUserByPasswordAndPermissionSet,
|
|
Client.GraphQL.ErrorCode.UserPasswordLength,
|
|
cancellationToken);
|
|
|
|
var oAuthCreateResult = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.CreateUserFromOAuthConnection.ExecuteAsync(
|
|
"TestUserWithNoPassword",
|
|
[
|
|
new()
|
|
{
|
|
ExternalUserId = "asdf",
|
|
Provider = Client.GraphQL.OAuthProvider.GitHub,
|
|
}
|
|
],
|
|
cancellationToken),
|
|
data => data.CreateUserByServiceConnectionAndPermissionSet,
|
|
cancellationToken);
|
|
|
|
var testUser2 = oAuthCreateResult.UpdatedUser;
|
|
|
|
var testUser22Result = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.SetUserGroup.ExecuteAsync(testUser2.Id, group.Id, cancellationToken),
|
|
data => data.UpdateUserSetGroup,
|
|
cancellationToken);
|
|
|
|
var testUser22 = testUser22Result.UpdatedUser.User;
|
|
|
|
Assert.IsNull(testUser22.OwnedPermissionSet);
|
|
Assert.IsNotNull(testUser22.Group);
|
|
Assert.AreEqual(group.Id, testUser22.Group.Id);
|
|
|
|
var group4Result = await client.RunQueryEnsureNoErrors(
|
|
gql => gql.GetSomeGroupInfo.ExecuteAsync(group.Id, cancellationToken),
|
|
cancellationToken);
|
|
var group4 = group4Result.Swarm.UserGroups.ById;
|
|
|
|
Assert.IsNotNull(group4.QueryableUsersByGroup.Nodes);
|
|
Assert.AreEqual(1, group4.QueryableUsersByGroup.TotalCount);
|
|
Assert.AreEqual(testUser2.Id, group4.QueryableUsersByGroup.Nodes[0].Id);
|
|
Assert.IsNotNull(group4.PermissionSet);
|
|
|
|
var testUser4Result = await client.RunMutationEnsureNoErrors(
|
|
gql => gql.SetUserPermissionSet.ExecuteAsync(
|
|
testUser2.Id,
|
|
new PermissionSetInput
|
|
{
|
|
AdministrationRights = new AdministrationRightsFlagsInput
|
|
{
|
|
CanChangeVersion = true,
|
|
CanDownloadLogs = true,
|
|
CanEditOwnServiceConnections = true,
|
|
CanEditOwnPassword = true,
|
|
CanReadUsers = true,
|
|
CanRestartHost = true,
|
|
CanUploadVersion = true,
|
|
CanWriteUsers = true,
|
|
},
|
|
InstanceManagerRights = new InstanceManagerRightsFlagsInput
|
|
{
|
|
CanCreate = true,
|
|
CanDelete = true,
|
|
CanGrantPermissions = true,
|
|
CanList = true,
|
|
CanRead = true,
|
|
CanRelocate = true,
|
|
CanRename = true,
|
|
CanSetAutoUpdate = true,
|
|
CanSetChatBotLimit = true,
|
|
CanSetConfiguration = true,
|
|
CanSetOnline = true,
|
|
CanSetAutoStart = true,
|
|
CanSetAutoStop = true,
|
|
}
|
|
},
|
|
cancellationToken),
|
|
data => data.UpdateUserSetOwnedPermissionSet,
|
|
cancellationToken);
|
|
|
|
var testUser4 = testUser4Result.UpdatedUser.User;
|
|
Assert.IsNull(testUser4.Group);
|
|
Assert.IsNotNull(testUser4.OwnedPermissionSet);
|
|
});
|
|
}
|
|
|
|
ValueTask TestCreateSysUser(CancellationToken cancellationToken)
|
|
{
|
|
var sysId = Environment.UserName;
|
|
|
|
return serverClient.Execute(
|
|
async restClient =>
|
|
{
|
|
var update = new UserCreateRequest
|
|
{
|
|
SystemIdentifier = sysId
|
|
};
|
|
if (new PlatformIdentifier().IsWindows)
|
|
await restClient.Users.Create(update, cancellationToken);
|
|
else
|
|
await ApiAssert.ThrowsExactly<MethodNotSupportedException, UserResponse>(() => restClient.Users.Create(update, cancellationToken), Api.Models.ErrorCode.RequiresPosixSystemIdentity);
|
|
},
|
|
async graphQLClient =>
|
|
{
|
|
if (new PlatformIdentifier().IsWindows)
|
|
{
|
|
await graphQLClient.RunMutationEnsureNoErrors(
|
|
gql => gql.CreateSystemUserWithPermissionSet.ExecuteAsync(sysId, cancellationToken),
|
|
data => data.CreateUserBySystemIDAndPermissionSet,
|
|
cancellationToken);
|
|
}
|
|
else
|
|
await ApiAssert.OperationFails(
|
|
graphQLClient,
|
|
gql => gql.CreateSystemUserWithPermissionSet.ExecuteAsync(sysId, cancellationToken),
|
|
data => data.CreateUserBySystemIDAndPermissionSet,
|
|
Client.GraphQL.ErrorCode.RequiresPosixSystemIdentity,
|
|
cancellationToken);
|
|
});
|
|
}
|
|
|
|
async ValueTask TestSpamCreation(CancellationToken cancellationToken)
|
|
{
|
|
// Careful with this, very easy to overload the thread pool
|
|
const int RepeatCount = 100;
|
|
var tasks = new List<ValueTask>(RepeatCount);
|
|
|
|
ThreadPool.GetMaxThreads(out var defaultMaxWorker, out var defaultMaxCompletion);
|
|
ThreadPool.GetMinThreads(out var defaultMinWorker, out var defaultMinCompletion);
|
|
ConcurrentBag<object> ids = new ConcurrentBag<object>();
|
|
try
|
|
{
|
|
ThreadPool.SetMinThreads(Math.Min(RepeatCount * 4, defaultMaxWorker), Math.Min(RepeatCount * 4, defaultMaxCompletion));
|
|
for (int i = 0; i < RepeatCount; ++i)
|
|
{
|
|
var iLocal = i;
|
|
ValueTask CreateSpamUser()
|
|
=> serverClient.Execute(
|
|
async restClient =>
|
|
{
|
|
var user = await restClient.Users.Create(
|
|
new UserCreateRequest
|
|
{
|
|
Name = $"SpamTestUser_{iLocal}",
|
|
Password = "asdfasdjfhauwiehruiy273894234jhndjkwh"
|
|
},
|
|
cancellationToken);
|
|
|
|
ids.Add(user.Id);
|
|
},
|
|
async graphQLClient =>
|
|
{
|
|
var result = await graphQLClient.RunMutationEnsureNoErrors(
|
|
gql => gql.CreateUserWithPassword.ExecuteAsync($"SpamTestUser_{iLocal}", "asdfasdjfhauwiehruiy273894234jhndjkwh", cancellationToken),
|
|
data => data.CreateUserByPasswordAndPermissionSet,
|
|
cancellationToken);
|
|
|
|
ids.Add(result.UpdatedUser.Id);
|
|
});
|
|
|
|
tasks.Add(CreateSpamUser());
|
|
}
|
|
|
|
await ValueTaskExtensions.WhenAll(tasks);
|
|
}
|
|
finally
|
|
{
|
|
ThreadPool.SetMinThreads(defaultMinWorker, defaultMinCompletion);
|
|
}
|
|
|
|
Assert.AreEqual(RepeatCount, ids.Distinct().Count(), "Did not receive expected number of unique user IDs!");
|
|
}
|
|
|
|
ValueTask TestPagination(CancellationToken cancellationToken)
|
|
{
|
|
var expectedCount = new PlatformIdentifier().IsWindows ? 106 : 105; // system user
|
|
return serverClient.Execute(
|
|
async restClient =>
|
|
{
|
|
// we test pagination here b/c it's the only spot we have a decent amount of entities
|
|
var nullSettings = await restClient.Users.List(null, cancellationToken);
|
|
var emptySettings = await restClient.Users.List(
|
|
new PaginationSettings
|
|
{
|
|
}, cancellationToken);
|
|
|
|
Assert.AreEqual(nullSettings.Count, emptySettings.Count);
|
|
Assert.AreEqual(expectedCount, nullSettings.Count);
|
|
Assert.IsTrue(nullSettings.All(x => emptySettings.SingleOrDefault(y => x.Id == y.Id) != null));
|
|
|
|
await ApiAssert.ThrowsExactly<ApiConflictException, List<UserResponse>>(() => restClient.Users.List(
|
|
new PaginationSettings
|
|
{
|
|
PageSize = -2143
|
|
}, cancellationToken), Api.Models.ErrorCode.ApiInvalidPageOrPageSize);
|
|
await ApiAssert.ThrowsExactly<ApiConflictException, List<UserResponse>>(() => restClient.Users.List(
|
|
new PaginationSettings
|
|
{
|
|
PageSize = ApiController.MaximumPageSize + 1,
|
|
}, cancellationToken), Api.Models.ErrorCode.ApiPageTooLarge);
|
|
|
|
var users = await restClient.Users.List(
|
|
new PaginationSettings
|
|
{
|
|
PageSize = ApiController.MaximumPageSize,
|
|
RetrieveCount = ApiController.MaximumPageSize,
|
|
},
|
|
cancellationToken);
|
|
|
|
Assert.AreEqual(ApiController.MaximumPageSize, users.Count);
|
|
|
|
var skipped = await restClient.Users.List(new PaginationSettings
|
|
{
|
|
Offset = 50,
|
|
RetrieveCount = 5
|
|
}, cancellationToken);
|
|
Assert.AreEqual(5, skipped.Count);
|
|
|
|
var allAfterSkipped = await restClient.Users.List(new PaginationSettings
|
|
{
|
|
Offset = 50,
|
|
}, cancellationToken);
|
|
Assert.IsTrue(5 < allAfterSkipped.Count);
|
|
|
|
var limited = await restClient.Users.List(new PaginationSettings
|
|
{
|
|
RetrieveCount = 12,
|
|
}, cancellationToken);
|
|
Assert.AreEqual(12, limited.Count);
|
|
},
|
|
graphQLClient =>
|
|
{
|
|
async ValueTask TestPageSize(int? inputPageSize)
|
|
{
|
|
var outputPageSize = inputPageSize ?? ApiController.DefaultPageSize;
|
|
|
|
string cursor = null;
|
|
|
|
var exactMatch = (expectedCount % outputPageSize) == 0;
|
|
var expectedIterations = (expectedCount / outputPageSize) + (exactMatch ? 0 : 1);
|
|
for (int i = 0; i < expectedIterations; ++i)
|
|
{
|
|
var isLastIteration = i == expectedIterations - 1;
|
|
var queryable = (await graphQLClient.RunQueryEnsureNoErrors(
|
|
gql => gql.PageUserIds.ExecuteAsync(inputPageSize, cursor, cancellationToken),
|
|
cancellationToken))
|
|
.Swarm
|
|
.Users
|
|
.QueryableUsers;
|
|
|
|
if (!isLastIteration || exactMatch)
|
|
Assert.AreEqual(outputPageSize, queryable.Nodes.Count);
|
|
else
|
|
Assert.AreEqual(expectedCount % outputPageSize, queryable.Nodes.Count);
|
|
Assert.AreEqual(!isLastIteration, queryable.PageInfo.HasNextPage);
|
|
Assert.IsNotNull(queryable.PageInfo.EndCursor);
|
|
|
|
cursor = queryable.PageInfo.EndCursor;
|
|
}
|
|
}
|
|
|
|
async ValueTask TestBadPageSize(int size)
|
|
{
|
|
var result = await graphQLClient.RunOperation(
|
|
gql => gql.PageUserIds.ExecuteAsync(size, null, cancellationToken),
|
|
cancellationToken);
|
|
|
|
if (size == 0)
|
|
{
|
|
// special case
|
|
result.EnsureNoErrors();
|
|
Assert.AreEqual(0, result.Data.Swarm.Users.QueryableUsers.Nodes.Count);
|
|
return;
|
|
}
|
|
|
|
var errored = result.IsErrorResult();
|
|
Assert.IsTrue(errored);
|
|
}
|
|
|
|
return ValueTaskExtensions.WhenAll(
|
|
TestPageSize(null),
|
|
TestPageSize(ApiController.DefaultPageSize),
|
|
TestPageSize(ApiController.DefaultPageSize / 2),
|
|
TestPageSize(ApiController.MaximumPageSize),
|
|
TestPageSize(1),
|
|
TestBadPageSize(-1),
|
|
TestBadPageSize(0),
|
|
TestBadPageSize(ApiController.MaximumPageSize + 1),
|
|
TestBadPageSize(Int32.MinValue),
|
|
TestBadPageSize(Int32.MaxValue));
|
|
});
|
|
}
|
|
}
|
|
}
|