1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-27 22:26:13 -05:00

add api integration tests for users WIP

This commit is contained in:
Brandon 2025-06-12 16:19:39 -04:00
parent bab0429adf
commit c11cef2bf2
No known key found for this signature in database
GPG Key ID: A0E0EF0B207BA40D
5 changed files with 136 additions and 26 deletions

View File

@ -54,25 +54,26 @@ public class OrganizationController : Controller
throw new BadRequestException("You cannot import this much data at once.");
}
string r = "";
r = await _importOrganizationUsersAndGroupsCommand.ImportAsync(
if (_featureService.IsEnabled(FeatureFlagKeys.ImportAsyncRefactor))
{
await _importOrganizationUsersAndGroupsCommand.ImportAsync(
_currentContext.OrganizationId.Value,
model.Groups.Select(g => g.ToImportedGroup(_currentContext.OrganizationId.Value)),
model.Members.Where(u => !u.Deleted).Select(u => u.ToImportedOrganizationUser()),
model.Members.Where(u => u.Deleted).Select(u => u.ExternalId),
model.OverwriteExisting.GetValueOrDefault());
if (_featureService.IsEnabled(FeatureFlagKeys.ImportAsyncRefactor))
{
r = "success";
}
else
{
r = "fail";
await _organizationService.ImportAsync(
_currentContext.OrganizationId.Value,
model.Groups.Select(g => g.ToImportedGroup(_currentContext.OrganizationId.Value)),
model.Members.Where(u => !u.Deleted).Select(u => u.ToImportedOrganizationUser()),
model.Members.Where(u => u.Deleted).Select(u => u.ExternalId),
model.OverwriteExisting.GetValueOrDefault(),
Core.Enums.EventSystemUser.PublicApi);
}
return new OkObjectResult(r);
return new OkResult();
}
}

View File

@ -7,7 +7,7 @@ namespace Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interface
public interface IImportOrganizationUsersAndGroupsCommand
{
Task<string> ImportAsync(Guid organizationId,
Task ImportAsync(Guid organizationId,
IEnumerable<ImportedGroup> groups,
IEnumerable<ImportedOrganizationUser> newUsers,
IEnumerable<string> removeUserExternalIds,

View File

@ -66,7 +66,7 @@ public class ImportOrganizationUsersAndGroupsCommand : IImportOrganizationUsersA
/// who are not included in the current import.</param>
/// <exception cref="NotFoundException">Thrown if the organization does not exist.</exception>
/// <exception cref="BadRequestException">Thrown if the organization is not configured to use directory syncing.</exception>
public async Task<string> ImportAsync(Guid organizationId,
public async Task ImportAsync(Guid organizationId,
IEnumerable<ImportedGroup> importedGroups,
IEnumerable<ImportedOrganizationUser> importedUsers,
IEnumerable<string> removeUserExternalIds,
@ -101,8 +101,6 @@ public class ImportOrganizationUsersAndGroupsCommand : IImportOrganizationUsersA
await ImportGroups(organization, importedGroups, importUserData);
await _eventService.LogOrganizationUserEventsAsync(events.Select(e => (e.ou, e.e, _EventSystemUser, e.d)));
return "success";
}
/// <summary>

View File

@ -1,11 +1,18 @@
using Bit.Api.AdminConsole.Public.Models.Request;
using System.Net;
using Bit.Api.AdminConsole.Public.Models.Request;
using Bit.Api.IntegrationTest.Factories;
using Bit.Api.IntegrationTest.Helpers;
using Bit.Core;
using Bit.Core.AdminConsole.Entities;
using Bit.Core.Billing.Enums;
using Bit.Core.Enums;
using Bit.Core.Repositories;
using Bit.Core.Services;
using NSubstitute;
using Xunit;
namespace Bit.Api.IntegrationTest.AdminConsole.Import;
public class ImportOrganizationUsersAndGroupsCommandTests : IClassFixture<ApiApplicationFactory>, IAsyncLifetime
{
private readonly HttpClient _client;
@ -17,8 +24,9 @@ public class ImportOrganizationUsersAndGroupsCommandTests : IClassFixture<ApiApp
public ImportOrganizationUsersAndGroupsCommandTests(ApiApplicationFactory factory)
{
_factory = factory;
_factory.UpdateConfiguration("globalSettings:launchDarkly:flagValues:pm-22583-refactor-import-async",
"true");
_factory.SubstituteService((IFeatureService featureService)
=> featureService.IsEnabled(FeatureFlagKeys.ImportAsyncRefactor)
.Returns(true));
_client = _factory.CreateClient();
_loginHelper = new LoginHelper(_factory, _client);
}
@ -44,11 +52,12 @@ public class ImportOrganizationUsersAndGroupsCommandTests : IClassFixture<ApiApp
}
[Fact]
public async Task Import_Existing_User_Success()
public async Task Import_Existing_Organization_User_Succeeds()
{
var (email, orgUser) = await OrganizationTestHelpers.CreateNewUserWithAccountAsync(_factory, _organization.Id,
var (email, ou) = await OrganizationTestHelpers.CreateNewUserWithAccountAsync(_factory, _organization.Id,
OrganizationUserType.User);
var externalId = Guid.NewGuid().ToString();
var request = new OrganizationImportRequestModel();
request.LargeImport = false;
request.OverwriteExisting = false;
@ -57,16 +66,117 @@ public class ImportOrganizationUsersAndGroupsCommandTests : IClassFixture<ApiApp
new OrganizationImportRequestModel.OrganizationImportMemberRequestModel
{
Email = email,
ExternalId = Guid.NewGuid().ToString(),
ExternalId = externalId,
Deleted = false
}
];
var response = await _client.PostAsync($"/public/organization/import", JsonContent.Create(request));
var result = await response.Content.ReadAsStringAsync();
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
Assert.Equal("success", result);
//Assert.Equal(HttpStatusCode.OK, response.StatusCode);
// Assert against the database values
var organizationUserRepository = _factory.GetService<IOrganizationUserRepository>();
var orgUser = await organizationUserRepository.GetByIdAsync(ou.Id);
Assert.NotNull(orgUser);
Assert.Equal(ou.Id, orgUser.Id);
Assert.Equal(email, orgUser.Email);
Assert.Equal(OrganizationUserType.User, orgUser.Type);
Assert.Equal(externalId, orgUser.ExternalId);
Assert.Equal(OrganizationUserStatusType.Confirmed, orgUser.Status);
Assert.Equal(_organization.Id, orgUser.OrganizationId);
}
[Fact]
public async Task Import_New_Organization_User_Succeeds()
{
var email = $"integration-test{Guid.NewGuid()}@bitwarden.com";
await _factory.LoginWithNewAccount(email);
var externalId = Guid.NewGuid().ToString();
var request = new OrganizationImportRequestModel();
request.LargeImport = false;
request.OverwriteExisting = false;
request.Groups = [];
request.Members = [
new OrganizationImportRequestModel.OrganizationImportMemberRequestModel
{
Email = email,
ExternalId = externalId,
Deleted = false
}
];
var response = await _client.PostAsync($"/public/organization/import", JsonContent.Create(request));
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
// Assert against the database values
var organizationUserRepository = _factory.GetService<IOrganizationUserRepository>();
var orgUser = await organizationUserRepository.GetByOrganizationEmailAsync(_organization.Id, email);
Assert.NotNull(orgUser);
Assert.Equal(email, orgUser.Email);
Assert.Equal(OrganizationUserType.User, orgUser.Type);
Assert.Equal(externalId, orgUser.ExternalId);
Assert.Equal(OrganizationUserStatusType.Invited, orgUser.Status);
Assert.Equal(_organization.Id, orgUser.OrganizationId);
}
[Fact]
public async Task Import_New_And_Existing_Organization_Users_Succeeds()
{
// Existing organization user
var (existingEmail, ou) = await OrganizationTestHelpers.CreateNewUserWithAccountAsync(_factory, _organization.Id,
OrganizationUserType.User);
var existingExternalId = Guid.NewGuid().ToString();
// New organization user
var newEmail = $"integration-test{Guid.NewGuid()}@bitwarden.com";
await _factory.LoginWithNewAccount(newEmail);
var newExternalId = Guid.NewGuid().ToString();
var request = new OrganizationImportRequestModel();
request.LargeImport = false;
request.OverwriteExisting = false;
request.Groups = [];
request.Members = [
new OrganizationImportRequestModel.OrganizationImportMemberRequestModel
{
Email = existingEmail,
ExternalId = existingExternalId,
Deleted = false
},
new OrganizationImportRequestModel.OrganizationImportMemberRequestModel
{
Email = newEmail,
ExternalId = newExternalId,
Deleted = false
}
];
var response = await _client.PostAsync($"/public/organization/import", JsonContent.Create(request));
Assert.Equal(HttpStatusCode.OK, response.StatusCode);
// Assert against the database values
var organizationUserRepository = _factory.GetService<IOrganizationUserRepository>();
// Existing user
var existingOrgUser = await organizationUserRepository.GetByIdAsync(ou.Id);
Assert.NotNull(existingOrgUser);
Assert.Equal(existingEmail, existingOrgUser.Email);
Assert.Equal(OrganizationUserType.User, existingOrgUser.Type);
Assert.Equal(existingExternalId, existingOrgUser.ExternalId);
Assert.Equal(OrganizationUserStatusType.Confirmed, existingOrgUser.Status);
Assert.Equal(_organization.Id, existingOrgUser.OrganizationId);
// New User
var newOrgUser = await organizationUserRepository.GetByOrganizationEmailAsync(_organization.Id, newEmail);
Assert.NotNull(newOrgUser);
Assert.Equal(newEmail, newOrgUser.Email);
Assert.Equal(OrganizationUserType.User, newOrgUser.Type);
Assert.Equal(newExternalId, newOrgUser.ExternalId);
Assert.Equal(OrganizationUserStatusType.Invited, newOrgUser.Status);
Assert.Equal(_organization.Id, newOrgUser.OrganizationId);
}
}

View File

@ -78,6 +78,7 @@ public static class OrganizationTestHelpers
Status = userStatusType,
ExternalId = null,
AccessSecretsManager = accessSecretsManager,
Email = userEmail
};
if (permissions != null)