mirror of
https://github.com/bitwarden/server.git
synced 2025-12-10 17:45:21 -06:00
* Add GroupsRecipe to manage group creation and user relationships in organizations
* Add CollectionsRecipe to manage collection creation and user relationships in organizations
* Refactor OrganizationUsersControllerPerformanceTests to enhance performance testing and add new test cases
* Add OrganizationDomainRecipe to add verified domains for organizations
* Add more tests to OrganizationUsersControllerPerformanceTests and enhance seeding logic for organizations
- Updated performance tests to use dynamic domain generation for organization users.
- Refactored seeding methods in OrganizationWithUsersRecipe to accept user status and type.
- Modified AddToOrganization methods in CollectionsRecipe and GroupsRecipe to return created IDs.
- Adjusted DbSeederUtility to align with new seeding method signatures.
* Enhance OrganizationSeeder with additional configuration options and update seat calculation in OrganizationWithUsersRecipe to ensure a minimum of 1000 seats.
* Add performance tests for Groups, Organizations, Organization Users, and Provider Organizations controllers
- Introduced `GroupsControllerPerformanceTests` to validate the performance of the PutGroupAsync method.
- Added `OrganizationsControllerPerformanceTests` with multiple tests including DeleteOrganizationAsync, DeleteOrganizationWithTokenAsync, PostStorageAsync, and CreateWithoutPaymentAsync.
- Enhanced `OrganizationUsersControllerPerformanceTests` with DeleteSingleUserAccountAsync and InviteUsersAsync methods to test user account deletion and bulk invitations.
- Created `ProviderOrganizationsControllerPerformanceTests` to assess the performance of deleting provider organizations.
These tests ensure the reliability and efficiency of the respective controller actions under various scenarios.
* Refactor GroupsControllerPerformanceTests to use parameterized tests
- Renamed `GroupsControllerPerformanceTest` to `GroupsControllerPerformanceTests` for consistency.
- Updated `PutGroupAsync` method to use `[Theory]` with `InlineData` for dynamic user and collection counts.
- Adjusted organization user and collection seeding logic to utilize the new parameters.
- Enhanced logging to provide clearer performance metrics during tests.
* Update domain generation in GroupsControllerPerformanceTests for improved test consistency
* Remove ProviderOrganizationsControllerPerformanceTests
* Refactor performance tests for Groups, Organizations, and Organization Users controllers
- Updated method names for clarity and consistency, e.g., `PutGroupAsync` to `UpdateGroup_WithUsersAndCollections`.
- Enhanced test documentation with XML comments to describe the purpose of each test.
- Improved domain generation logic for consistency across tests.
- Adjusted logging to provide detailed performance metrics during test execution.
- Renamed several test methods to better reflect their functionality.
* Refactor performance tests in Organizations and Organization Users controllers
- Updated tests to use parameterized `[Theory]` attributes with `InlineData` for dynamic user, collection, and group counts.
- Enhanced logging to include detailed metrics such as user and collection counts during test execution.
- Marked several tests as skipped for performance considerations.
- Removed unused code and improved organization of test methods for clarity.
* Add bulk reinvite users performance test to OrganizationUsersControllerPerformanceTests
- Implemented a new performance test for the POST /organizations/{orgId}/users/reinvite endpoint.
- Utilized parameterized testing with `[Theory]` and `InlineData` to evaluate performance with varying user counts.
- Enhanced logging to capture request duration and response status for better performance insights.
- Updated OrganizationSeeder to conditionally set email based on user status during seeding.
* Refactor domain generation in performance tests to use OrganizationTestHelpers
- Updated domain generation logic in GroupsControllerPerformanceTests, OrganizationsControllerPerformanceTests, and OrganizationUsersControllerPerformanceTests to utilize the new GenerateRandomDomain method from OrganizationTestHelpers.
- This change enhances consistency and readability across the tests by centralizing domain generation logic.
* Update CollectionsRecipe to have better readability
* Update GroupsRecipe to have better readability
* Refactor authentication in performance tests to use centralized helper method. This change reduces code duplication across Groups, Organizations, and OrganizationUsers controller tests by implementing the `AuthenticateClientAsync` method in a new `PerformanceTestHelpers` class.
* Refactor OrganizationUsersControllerPerformanceTests to filter organization users by OrganizationId.
* Refactor CreateOrganizationUser method to improve handling of user status and key assignment based on invitation and confirmation states.
* Add XML documentation for CreateOrganizationUser method to clarify user status handling
594 lines
23 KiB
C#
594 lines
23 KiB
C#
using System.Net;
|
|
using System.Text;
|
|
using System.Text.Json;
|
|
using Bit.Api.AdminConsole.Models.Request.Organizations;
|
|
using Bit.Api.IntegrationTest.Factories;
|
|
using Bit.Api.IntegrationTest.Helpers;
|
|
using Bit.Api.Models.Request;
|
|
using Bit.Core.Enums;
|
|
using Bit.Core.Models.Data;
|
|
using Bit.Seeder.Recipes;
|
|
using Xunit;
|
|
using Xunit.Abstractions;
|
|
|
|
namespace Bit.Api.IntegrationTest.AdminConsole.Controllers;
|
|
|
|
public class OrganizationUsersControllerPerformanceTests(ITestOutputHelper testOutputHelper)
|
|
{
|
|
/// <summary>
|
|
/// Tests GET /organizations/{orgId}/users?includeCollections=true
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task GetAllUsers_WithCollections(int seats)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var collectionsSeeder = new CollectionsRecipe(db);
|
|
var groupsSeeder = new GroupsRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: seats);
|
|
|
|
var orgUserIds = db.OrganizationUsers.Where(ou => ou.OrganizationId == orgId).Select(ou => ou.Id).ToList();
|
|
collectionsSeeder.AddToOrganization(orgId, 10, orgUserIds);
|
|
groupsSeeder.AddToOrganization(orgId, 5, orgUserIds);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.GetAsync($"/organizations/{orgId}/users?includeCollections=true");
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
|
|
stopwatch.Stop();
|
|
testOutputHelper.WriteLine($"GET /users - Seats: {seats}; Request duration: {stopwatch.ElapsedMilliseconds} ms");
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests GET /organizations/{orgId}/users/mini-details
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task GetAllUsers_MiniDetails(int seats)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var collectionsSeeder = new CollectionsRecipe(db);
|
|
var groupsSeeder = new GroupsRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: seats);
|
|
|
|
var orgUserIds = db.OrganizationUsers.Where(ou => ou.OrganizationId == orgId).Select(ou => ou.Id).ToList();
|
|
collectionsSeeder.AddToOrganization(orgId, 10, orgUserIds);
|
|
groupsSeeder.AddToOrganization(orgId, 5, orgUserIds);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.GetAsync($"/organizations/{orgId}/users/mini-details");
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"GET /users/mini-details - Seats: {seats}; Request duration: {stopwatch.ElapsedMilliseconds} ms");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests GET /organizations/{orgId}/users/{id}?includeGroups=true
|
|
/// </summary>
|
|
[Fact(Skip = "Performance test")]
|
|
public async Task GetSingleUser_WithGroups()
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var groupsSeeder = new GroupsRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: 1);
|
|
|
|
var orgUserId = db.OrganizationUsers.Where(ou => ou.OrganizationId == orgId).Select(ou => ou.Id).FirstOrDefault();
|
|
groupsSeeder.AddToOrganization(orgId, 2, [orgUserId]);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.GetAsync($"/organizations/{orgId}/users/{orgUserId}?includeGroups=true");
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"GET /users/{{id}} - Request duration: {stopwatch.ElapsedMilliseconds} ms");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests GET /organizations/{orgId}/users/{id}/reset-password-details
|
|
/// </summary>
|
|
[Fact(Skip = "Performance test")]
|
|
public async Task GetResetPasswordDetails_ForSingleUser()
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: 1);
|
|
|
|
var orgUserId = db.OrganizationUsers.Where(ou => ou.OrganizationId == orgId).Select(ou => ou.Id).FirstOrDefault();
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.GetAsync($"/organizations/{orgId}/users/{orgUserId}/reset-password-details");
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"GET /users/{{id}}/reset-password-details - Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests POST /organizations/{orgId}/users/confirm
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkConfirmUsers(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(
|
|
name: "Org",
|
|
domain: domain,
|
|
users: userCount,
|
|
usersStatus: OrganizationUserStatusType.Accepted);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var acceptedUserIds = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Status == OrganizationUserStatusType.Accepted)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var confirmRequest = new OrganizationUserBulkConfirmRequestModel
|
|
{
|
|
Keys = acceptedUserIds.Select(id => new OrganizationUserBulkConfirmRequestModelEntry { Id = id, Key = "test-key-" + id }),
|
|
DefaultUserCollectionName = "2.AOs41Hd8OQiCPXjyJKCiDA==|O6OHgt2U2hJGBSNGnimJmg==|iD33s8B69C8JhYYhSa4V1tArjvLr8eEaGqOV7BRo5Jk="
|
|
};
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(confirmRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PostAsync($"/organizations/{orgId}/users/confirm", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"POST /users/confirm - Users: {acceptedUserIds.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests POST /organizations/{orgId}/users/remove
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkRemoveUsers(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: userCount);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var usersToRemove = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var removeRequest = new OrganizationUserBulkRequestModel { Ids = usersToRemove };
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(removeRequest), Encoding.UTF8, "application/json");
|
|
|
|
var response = await client.PostAsync($"/organizations/{orgId}/users/remove", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"POST /users/remove - Users: {usersToRemove.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests PUT /organizations/{orgId}/users/revoke
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkRevokeUsers(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(
|
|
name: "Org",
|
|
domain: domain,
|
|
users: userCount,
|
|
usersStatus: OrganizationUserStatusType.Confirmed);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var usersToRevoke = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var revokeRequest = new OrganizationUserBulkRequestModel { Ids = usersToRevoke };
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(revokeRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PutAsync($"/organizations/{orgId}/users/revoke", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"PUT /users/revoke - Users: {usersToRevoke.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests PUT /organizations/{orgId}/users/restore
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkRestoreUsers(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(
|
|
name: "Org",
|
|
domain: domain,
|
|
users: userCount,
|
|
usersStatus: OrganizationUserStatusType.Revoked);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var usersToRestore = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var restoreRequest = new OrganizationUserBulkRequestModel { Ids = usersToRestore };
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(restoreRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PutAsync($"/organizations/{orgId}/users/restore", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"PUT /users/restore - Users: {usersToRestore.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests POST /organizations/{orgId}/users/delete-account
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkDeleteAccounts(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var domainSeeder = new OrganizationDomainRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
|
|
var orgId = orgSeeder.Seed(
|
|
name: "Org",
|
|
domain: domain,
|
|
users: userCount,
|
|
usersStatus: OrganizationUserStatusType.Confirmed);
|
|
|
|
domainSeeder.AddVerifiedDomainToOrganization(orgId, domain);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var usersToDelete = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var deleteRequest = new OrganizationUserBulkRequestModel { Ids = usersToDelete };
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(deleteRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PostAsync($"/organizations/{orgId}/users/delete-account", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"POST /users/delete-account - Users: {usersToDelete.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests PUT /organizations/{orgId}/users/{id}
|
|
/// </summary>
|
|
[Fact(Skip = "Performance test")]
|
|
public async Task UpdateSingleUser_WithCollectionsAndGroups()
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var collectionsSeeder = new CollectionsRecipe(db);
|
|
var groupsSeeder = new GroupsRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: 1);
|
|
|
|
var orgUserIds = db.OrganizationUsers.Where(ou => ou.OrganizationId == orgId).Select(ou => ou.Id).ToList();
|
|
var collectionIds = collectionsSeeder.AddToOrganization(orgId, 3, orgUserIds, 0);
|
|
var groupIds = groupsSeeder.AddToOrganization(orgId, 2, orgUserIds, 0);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var userToUpdate = db.OrganizationUsers
|
|
.FirstOrDefault(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User);
|
|
|
|
var updateRequest = new OrganizationUserUpdateRequestModel
|
|
{
|
|
Type = OrganizationUserType.Custom,
|
|
Collections = collectionIds.Select(c => new SelectionReadOnlyRequestModel { Id = c, ReadOnly = false, HidePasswords = false, Manage = false }),
|
|
Groups = groupIds,
|
|
AccessSecretsManager = false,
|
|
Permissions = new Permissions { AccessEventLogs = true }
|
|
};
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PutAsync($"/organizations/{orgId}/users/{userToUpdate.Id}",
|
|
new StringContent(JsonSerializer.Serialize(updateRequest), Encoding.UTF8, "application/json"));
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"PUT /users/{{id}} - Collections: {collectionIds.Count}; Groups: {groupIds.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests PUT /organizations/{orgId}/users/enable-secrets-manager
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkEnableSecretsManager(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: userCount);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var usersToEnable = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var enableRequest = new OrganizationUserBulkRequestModel { Ids = usersToEnable };
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(enableRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PutAsync($"/organizations/{orgId}/users/enable-secrets-manager", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"PUT /users/enable-secrets-manager - Users: {usersToEnable.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests DELETE /organizations/{orgId}/users/{id}/delete-account
|
|
/// </summary>
|
|
[Fact(Skip = "Performance test")]
|
|
public async Task DeleteSingleUserAccount_FromVerifiedDomain()
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var domainSeeder = new OrganizationDomainRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(
|
|
name: "Org",
|
|
domain: domain,
|
|
users: 2,
|
|
usersStatus: OrganizationUserStatusType.Confirmed);
|
|
|
|
domainSeeder.AddVerifiedDomainToOrganization(orgId, domain);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var userToDelete = db.OrganizationUsers
|
|
.FirstOrDefault(ou => ou.OrganizationId == orgId && ou.Type == OrganizationUserType.User);
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.DeleteAsync($"/organizations/{orgId}/users/{userToDelete.Id}/delete-account");
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"DELETE /users/{{id}}/delete-account - Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests POST /organizations/{orgId}/users/invite
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(1)]
|
|
//[InlineData(5)]
|
|
//[InlineData(20)]
|
|
public async Task InviteUsers(int emailCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
var collectionsSeeder = new CollectionsRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(name: "Org", domain: domain, users: 1);
|
|
|
|
var orgUserIds = db.OrganizationUsers.Where(ou => ou.OrganizationId == orgId).Select(ou => ou.Id).ToList();
|
|
var collectionIds = collectionsSeeder.AddToOrganization(orgId, 2, orgUserIds, 0);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var emails = Enumerable.Range(0, emailCount).Select(i => $"{i:D4}@{domain}").ToArray();
|
|
var inviteRequest = new OrganizationUserInviteRequestModel
|
|
{
|
|
Emails = emails,
|
|
Type = OrganizationUserType.User,
|
|
AccessSecretsManager = false,
|
|
Collections = Array.Empty<SelectionReadOnlyRequestModel>(),
|
|
Groups = Array.Empty<Guid>(),
|
|
Permissions = null
|
|
};
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(inviteRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PostAsync($"/organizations/{orgId}/users/invite", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"POST /users/invite - Emails: {emails.Length}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Tests POST /organizations/{orgId}/users/reinvite
|
|
/// </summary>
|
|
[Theory(Skip = "Performance test")]
|
|
[InlineData(10)]
|
|
//[InlineData(100)]
|
|
//[InlineData(1000)]
|
|
public async Task BulkReinviteUsers(int userCount)
|
|
{
|
|
await using var factory = new SqlServerApiApplicationFactory();
|
|
var client = factory.CreateClient();
|
|
|
|
var db = factory.GetDatabaseContext();
|
|
var orgSeeder = new OrganizationWithUsersRecipe(db);
|
|
|
|
var domain = OrganizationTestHelpers.GenerateRandomDomain();
|
|
var orgId = orgSeeder.Seed(
|
|
name: "Org",
|
|
domain: domain,
|
|
users: userCount,
|
|
usersStatus: OrganizationUserStatusType.Invited);
|
|
|
|
await PerformanceTestHelpers.AuthenticateClientAsync(factory, client, $"owner@{domain}");
|
|
|
|
var usersToReinvite = db.OrganizationUsers
|
|
.Where(ou => ou.OrganizationId == orgId && ou.Status == OrganizationUserStatusType.Invited)
|
|
.Select(ou => ou.Id)
|
|
.ToList();
|
|
|
|
var reinviteRequest = new OrganizationUserBulkRequestModel { Ids = usersToReinvite };
|
|
|
|
var requestContent = new StringContent(JsonSerializer.Serialize(reinviteRequest), Encoding.UTF8, "application/json");
|
|
|
|
var stopwatch = System.Diagnostics.Stopwatch.StartNew();
|
|
|
|
var response = await client.PostAsync($"/organizations/{orgId}/users/reinvite", requestContent);
|
|
|
|
stopwatch.Stop();
|
|
|
|
testOutputHelper.WriteLine($"POST /users/reinvite - Users: {usersToReinvite.Count}; Request duration: {stopwatch.ElapsedMilliseconds} ms; Status: {response.StatusCode}");
|
|
|
|
Assert.True(response.IsSuccessStatusCode);
|
|
}
|
|
}
|