mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 00:22:50 -05:00
Merge branch 'master' into feature/flexible-collections
This commit is contained in:
@ -116,6 +116,19 @@ public class ProjectsControllerTests : IClassFixture<ApiApplicationFactory>, IAs
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task Create_AtMaxProjects_BadRequest(PermissionType permissionType)
|
||||
{
|
||||
var (_, organization) = await SetupProjectsWithAccessAsync(permissionType, 3);
|
||||
var request = new ProjectCreateRequestModel { Name = _mockEncryptedString };
|
||||
|
||||
var response = await _client.PostAsJsonAsync($"/organizations/{organization.Id}/projects", request);
|
||||
|
||||
Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
|
@ -709,6 +709,69 @@ public class SecretsControllerTests : IClassFixture<ApiApplicationFactory>, IAsy
|
||||
Assert.Empty(secrets);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(false, false)]
|
||||
[InlineData(true, false)]
|
||||
[InlineData(false, true)]
|
||||
public async Task GetSecretsByIds_SmNotEnabled_NotFound(bool useSecrets, bool accessSecrets)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(useSecrets, accessSecrets);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var secret = await _secretRepository.CreateAsync(new Secret
|
||||
{
|
||||
OrganizationId = org.Id,
|
||||
Key = _mockEncryptedString,
|
||||
Value = _mockEncryptedString,
|
||||
Note = _mockEncryptedString,
|
||||
});
|
||||
|
||||
var request = new GetSecretsRequestModel { Ids = new[] { secret.Id } };
|
||||
|
||||
var response = await _client.PostAsJsonAsync("/secrets/get-by-ids", request);
|
||||
Assert.Equal(HttpStatusCode.NotFound, response.StatusCode);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(PermissionType.RunAsAdmin)]
|
||||
[InlineData(PermissionType.RunAsUserWithPermission)]
|
||||
public async Task GetSecretsByIds_Success(PermissionType permissionType)
|
||||
{
|
||||
var (org, _) = await _organizationHelper.Initialize(true, true);
|
||||
await LoginAsync(_email);
|
||||
|
||||
var (project, secretIds) = await CreateSecretsAsync(org.Id);
|
||||
|
||||
if (permissionType == PermissionType.RunAsUserWithPermission)
|
||||
{
|
||||
var (email, orgUser) = await _organizationHelper.CreateNewUser(OrganizationUserType.User, true);
|
||||
await LoginAsync(email);
|
||||
|
||||
var accessPolicies = new List<BaseAccessPolicy>
|
||||
{
|
||||
new UserProjectAccessPolicy
|
||||
{
|
||||
GrantedProjectId = project.Id, OrganizationUserId = orgUser.Id, Read = true, Write = true,
|
||||
},
|
||||
};
|
||||
await _accessPolicyRepository.CreateManyAsync(accessPolicies);
|
||||
}
|
||||
else
|
||||
{
|
||||
var (email, _) = await _organizationHelper.CreateNewUser(OrganizationUserType.Admin, true);
|
||||
await LoginAsync(email);
|
||||
}
|
||||
|
||||
var request = new GetSecretsRequestModel { Ids = secretIds };
|
||||
|
||||
var response = await _client.PostAsJsonAsync("/secrets/get-by-ids", request);
|
||||
response.EnsureSuccessStatusCode();
|
||||
var result = await response.Content.ReadFromJsonAsync<ListResponseModel<BaseSecretResponseModel>>();
|
||||
Assert.NotNull(result);
|
||||
Assert.NotEmpty(result!.Data);
|
||||
Assert.Equal(secretIds.Count, result!.Data.Count());
|
||||
}
|
||||
|
||||
private async Task<(Project Project, List<Guid> secretIds)> CreateSecretsAsync(Guid orgId, int numberToCreate = 3)
|
||||
{
|
||||
var project = await _projectRepository.CreateAsync(new Project
|
||||
|
@ -8,6 +8,7 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.SecretsManager.Commands.Projects.Interfaces;
|
||||
using Bit.Core.SecretsManager.Entities;
|
||||
using Bit.Core.SecretsManager.Models.Data;
|
||||
using Bit.Core.SecretsManager.Queries.Projects.Interfaces;
|
||||
using Bit.Core.SecretsManager.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.SecretsManager.AutoFixture.ProjectsFixture;
|
||||
@ -122,6 +123,24 @@ public class ProjectsControllerTests
|
||||
.CreateAsync(Arg.Any<Project>(), Arg.Any<Guid>(), sutProvider.GetDependency<ICurrentContext>().ClientType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void Create_AtMaxProjects_Throws(SutProvider<ProjectsController> sutProvider,
|
||||
Guid orgId, ProjectCreateRequestModel data)
|
||||
{
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), data.ToProject(orgId),
|
||||
Arg.Any<IEnumerable<IAuthorizationRequirement>>()).ReturnsForAnyArgs(AuthorizationResult.Success());
|
||||
sutProvider.GetDependency<IUserService>().GetProperUserId(default).ReturnsForAnyArgs(Guid.NewGuid());
|
||||
sutProvider.GetDependency<IMaxProjectsQuery>().GetByOrgIdAsync(orgId).Returns(((short)3, true));
|
||||
|
||||
|
||||
await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.CreateAsync(orgId, data));
|
||||
|
||||
await sutProvider.GetDependency<ICreateProjectCommand>().DidNotReceiveWithAnyArgs()
|
||||
.CreateAsync(Arg.Any<Project>(), Arg.Any<Guid>(), sutProvider.GetDependency<ICurrentContext>().ClientType);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void Create_Success(SutProvider<ProjectsController> sutProvider,
|
||||
|
@ -346,4 +346,105 @@ public class SecretsControllerTests
|
||||
Assert.Null(result.Error);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetSecretsByIds_NoSecretsFound_ThrowsNotFound(SutProvider<SecretsController> sutProvider,
|
||||
List<Secret> data)
|
||||
{
|
||||
var (ids, request) = BuildGetSecretsRequestModel(data);
|
||||
sutProvider.GetDependency<ISecretRepository>().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(new List<Secret>());
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetSecretsByIdsAsync(request));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetSecretsByIds_SecretsFoundMisMatch_ThrowsNotFound(SutProvider<SecretsController> sutProvider,
|
||||
List<Secret> data, Secret mockSecret)
|
||||
{
|
||||
var (ids, request) = BuildGetSecretsRequestModel(data);
|
||||
ids.Add(mockSecret.Id);
|
||||
sutProvider.GetDependency<ISecretRepository>().GetManyByIds(Arg.Is(ids))
|
||||
.ReturnsForAnyArgs(new List<Secret> { mockSecret });
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetSecretsByIdsAsync(request));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetSecretsByIds_OrganizationMisMatch_ThrowsNotFound(SutProvider<SecretsController> sutProvider,
|
||||
List<Secret> data)
|
||||
{
|
||||
var (ids, request) = BuildGetSecretsRequestModel(data);
|
||||
sutProvider.GetDependency<ISecretRepository>().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data);
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetSecretsByIdsAsync(request));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetSecretsByIds_NoAccessToSecretsManager_ThrowsNotFound(
|
||||
SutProvider<SecretsController> sutProvider, List<Secret> data)
|
||||
{
|
||||
var (ids, request) = BuildGetSecretsRequestModel(data);
|
||||
var organizationId = SetOrganizations(ref data);
|
||||
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Is(organizationId))
|
||||
.ReturnsForAnyArgs(false);
|
||||
sutProvider.GetDependency<ISecretRepository>().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data);
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetSecretsByIdsAsync(request));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetSecretsByIds_AccessDenied_ThrowsNotFound(SutProvider<SecretsController> sutProvider,
|
||||
List<Secret> data)
|
||||
{
|
||||
var (ids, request) = BuildGetSecretsRequestModel(data);
|
||||
var organizationId = SetOrganizations(ref data);
|
||||
|
||||
sutProvider.GetDependency<ISecretRepository>().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data);
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Is(organizationId))
|
||||
.ReturnsForAnyArgs(true);
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), data.First(),
|
||||
Arg.Any<IEnumerable<IAuthorizationRequirement>>()).ReturnsForAnyArgs(AuthorizationResult.Failed());
|
||||
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.GetSecretsByIdsAsync(request));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async void GetSecretsByIds_Success(SutProvider<SecretsController> sutProvider, List<Secret> data)
|
||||
{
|
||||
var (ids, request) = BuildGetSecretsRequestModel(data);
|
||||
var organizationId = SetOrganizations(ref data);
|
||||
|
||||
sutProvider.GetDependency<ISecretRepository>().GetManyByIds(Arg.Is(ids)).ReturnsForAnyArgs(data);
|
||||
sutProvider.GetDependency<ICurrentContext>().AccessSecretsManager(Arg.Is(organizationId))
|
||||
.ReturnsForAnyArgs(true);
|
||||
sutProvider.GetDependency<IAuthorizationService>()
|
||||
.AuthorizeAsync(Arg.Any<ClaimsPrincipal>(), data.First(),
|
||||
Arg.Any<IEnumerable<IAuthorizationRequirement>>()).ReturnsForAnyArgs(AuthorizationResult.Success());
|
||||
|
||||
var results = await sutProvider.Sut.GetSecretsByIdsAsync(request);
|
||||
Assert.Equal(data.Count, results.Data.Count());
|
||||
}
|
||||
|
||||
private static (List<Guid> Ids, GetSecretsRequestModel request) BuildGetSecretsRequestModel(
|
||||
IEnumerable<Secret> data)
|
||||
{
|
||||
var ids = data.Select(s => s.Id).ToList();
|
||||
var request = new GetSecretsRequestModel { Ids = ids };
|
||||
return (ids, request);
|
||||
}
|
||||
|
||||
private static Guid SetOrganizations(ref List<Secret> data)
|
||||
{
|
||||
var organizationId = data.First().OrganizationId;
|
||||
foreach (var s in data)
|
||||
{
|
||||
s.OrganizationId = organizationId;
|
||||
}
|
||||
|
||||
return organizationId;
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ using Bit.Core.Context;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Models.Business;
|
||||
using Bit.Core.OrganizationFeatures.OrganizationSubscriptions.Interface;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.SecretsManager.Commands.AccessTokens.Interfaces;
|
||||
@ -106,7 +107,7 @@ public class ServiceAccountsControllerTests
|
||||
.CreateAsync(Arg.Is<ServiceAccount>(sa => sa.Name == data.Name), Arg.Any<Guid>());
|
||||
|
||||
await sutProvider.GetDependency<IUpdateSecretsManagerSubscriptionCommand>().DidNotReceiveWithAnyArgs()
|
||||
.AdjustServiceAccountsAsync(Arg.Any<Organization>(), Arg.Any<int>());
|
||||
.UpdateSubscriptionAsync(Arg.Any<SecretsManagerSubscriptionUpdate>());
|
||||
}
|
||||
|
||||
[Theory]
|
||||
@ -124,7 +125,12 @@ public class ServiceAccountsControllerTests
|
||||
.CreateAsync(Arg.Is<ServiceAccount>(sa => sa.Name == data.Name), Arg.Any<Guid>());
|
||||
|
||||
await sutProvider.GetDependency<IUpdateSecretsManagerSubscriptionCommand>().Received(1)
|
||||
.AdjustServiceAccountsAsync(Arg.Is(organization), Arg.Is(newSlotsRequired));
|
||||
.UpdateSubscriptionAsync(Arg.Is<SecretsManagerSubscriptionUpdate>(update =>
|
||||
update.Autoscaling == true &&
|
||||
update.SmServiceAccounts == organization.SmServiceAccounts + newSlotsRequired &&
|
||||
!update.SmSeatsChanged &&
|
||||
!update.MaxAutoscaleSmSeatsChanged &&
|
||||
!update.MaxAutoscaleSmServiceAccountsChanged));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
|
@ -32,7 +32,7 @@ internal class CurrentContextBuilder : ISpecimenBuilder
|
||||
}
|
||||
|
||||
var obj = new Fixture().WithAutoNSubstitutions().Create<ICurrentContext>();
|
||||
obj.Organizations = context.Create<List<CurrentContentOrganization>>();
|
||||
obj.Organizations = context.Create<List<CurrentContextOrganization>>();
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +137,7 @@ public class SecretsManagerOrganizationCustomization : ICustomization
|
||||
fixture.Customize<Organization>(composer => composer
|
||||
.With(o => o.Id, organizationId)
|
||||
.With(o => o.UseSecretsManager, true)
|
||||
.With(o => o.SecretsManagerBeta, false)
|
||||
.With(o => o.PlanType, planType)
|
||||
.With(o => o.Plan, StaticStore.GetPasswordManagerPlan(planType).Name)
|
||||
.With(o => o.MaxAutoscaleSmSeats, (int?)null)
|
||||
|
@ -95,6 +95,38 @@ public class AddSecretsManagerSubscriptionCommandTests
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SignUpAsync_ThrowsException_WhenOrganizationEnrolledInSmBeta(
|
||||
SutProvider<AddSecretsManagerSubscriptionCommand> sutProvider,
|
||||
Organization organization)
|
||||
{
|
||||
organization.UseSecretsManager = true;
|
||||
organization.SecretsManagerBeta = true;
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpAsync(organization, 10, 10));
|
||||
|
||||
Assert.Contains("Organization is enrolled in Secrets Manager Beta", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SignUpAsync_ThrowsException_WhenOrganizationAlreadyHasSecretsManager(
|
||||
SutProvider<AddSecretsManagerSubscriptionCommand> sutProvider,
|
||||
Organization organization)
|
||||
{
|
||||
organization.UseSecretsManager = true;
|
||||
organization.SecretsManagerBeta = false;
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SignUpAsync(organization, 10, 10));
|
||||
|
||||
Assert.Contains("Organization already uses Secrets Manager", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
private static async Task VerifyDependencyNotCalledAsync(SutProvider<AddSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
await sutProvider.GetDependency<IPaymentService>().DidNotReceive()
|
||||
|
@ -125,8 +125,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, autoscaling);
|
||||
update.AdjustSeats(2);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, autoscaling).AdjustSeats(2);
|
||||
|
||||
sutProvider.GetDependency<IGlobalSettings>().SelfHosted.Returns(true);
|
||||
|
||||
@ -151,6 +150,23 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task UpdateSubscriptionAsync_OrganizationEnrolledInSmBeta_ThrowsException(
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider,
|
||||
Organization organization)
|
||||
{
|
||||
organization.UseSecretsManager = true;
|
||||
organization.SecretsManagerBeta = true;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
|
||||
Assert.Contains("Organization is enrolled in Secrets Manager Beta", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(PlanType.EnterpriseAnnually)]
|
||||
[BitAutoData(PlanType.EnterpriseMonthly)]
|
||||
@ -163,8 +179,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.GatewayCustomerId = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustSeats(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("No payment method found.", exception.Message);
|
||||
@ -183,8 +198,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
organization.GatewaySubscriptionId = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustSeats(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("No subscription found.", exception.Message);
|
||||
@ -223,8 +237,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
var expectedSmServiceAccounts = organizationServiceAccounts + smServiceAccountsAdjustment;
|
||||
var expectedSmServiceAccountsExcludingBase = expectedSmServiceAccounts - plan.BaseServiceAccount.GetValueOrDefault();
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustServiceAccounts(10);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustServiceAccounts(10);
|
||||
|
||||
await sutProvider.Sut.UpdateSubscriptionAsync(update);
|
||||
|
||||
@ -247,7 +260,6 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmSeats = 9;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
{
|
||||
SmSeats = 10,
|
||||
@ -267,8 +279,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmSeats = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustSeats(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
@ -283,8 +294,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true);
|
||||
update.AdjustSeats(-2);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustSeats(-2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Cannot use autoscaling to subtract seats.", exception.Message);
|
||||
@ -299,8 +309,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustSeats(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustSeats(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("You have reached the maximum number of Secrets Manager seats (2) for this plan",
|
||||
@ -317,8 +326,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.SmSeats = 9;
|
||||
organization.MaxAutoscaleSmSeats = 10;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true);
|
||||
update.AdjustSeats(2);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustSeats(2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Secrets Manager seat limit has been reached.", exception.Message);
|
||||
@ -375,7 +383,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
sutProvider.GetDependency<IOrganizationUserRepository>().GetOccupiedSmSeatCountByOrganizationIdAsync(organization.Id).Returns(8);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Your organization currently has 8 Secrets Manager seats. Your plan only allows 7 Secrets Manager seats. Remove some Secrets Manager users", exception.Message);
|
||||
Assert.Contains("8 users are currently occupying Secrets Manager seats. You cannot decrease your subscription below your current occupied seat count", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
@ -385,7 +393,6 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmServiceAccounts = 250;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false)
|
||||
{
|
||||
SmServiceAccounts = 300,
|
||||
@ -405,11 +412,10 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.SmServiceAccounts = null;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustServiceAccounts(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustServiceAccounts(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Organization has no Service Accounts limit, no need to adjust Service Accounts", exception.Message);
|
||||
Assert.Contains("Organization has no service accounts limit, no need to adjust service accounts", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
@ -419,8 +425,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
Organization organization,
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true);
|
||||
update.AdjustServiceAccounts(-2);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustServiceAccounts(-2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Cannot use autoscaling to subtract service accounts.", exception.Message);
|
||||
@ -435,8 +440,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
SutProvider<UpdateSecretsManagerSubscriptionCommand> sutProvider)
|
||||
{
|
||||
organization.PlanType = planType;
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false);
|
||||
update.AdjustServiceAccounts(1);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false).AdjustServiceAccounts(1);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("You have reached the maximum number of service accounts (3) for this plan",
|
||||
@ -453,8 +457,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
organization.SmServiceAccounts = 9;
|
||||
organization.MaxAutoscaleSmServiceAccounts = 10;
|
||||
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true);
|
||||
update.AdjustServiceAccounts(2);
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, true).AdjustServiceAccounts(2);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Secrets Manager service account limit has been reached.", exception.Message);
|
||||
@ -492,7 +495,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Plan has a minimum of 200 Service Accounts", exception.Message);
|
||||
Assert.Contains("Plan has a minimum of 200 service accounts", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
@ -516,7 +519,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
.Returns(currentServiceAccounts);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Your organization currently has 301 Service Accounts. Your plan only allows 201 Service Accounts. Remove some Service Accounts", exception.Message);
|
||||
Assert.Contains("Your organization currently has 301 service accounts. You cannot decrease your subscription below your current service account usage", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
@ -588,7 +591,7 @@ public class UpdateSecretsManagerSubscriptionCommandTests
|
||||
var update = new SecretsManagerSubscriptionUpdate(organization, false) { MaxAutoscaleSmServiceAccounts = 3 };
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() => sutProvider.Sut.UpdateSubscriptionAsync(update));
|
||||
Assert.Contains("Your plan does not allow Service Accounts autoscaling.", exception.Message);
|
||||
Assert.Contains("Your plan does not allow service accounts autoscaling.", exception.Message);
|
||||
await VerifyDependencyNotCalledAsync(sutProvider);
|
||||
}
|
||||
|
||||
|
@ -648,6 +648,7 @@ public class OrganizationServiceTests
|
||||
[OrganizationUser(type: OrganizationUserType.Owner, status: OrganizationUserStatusType.Confirmed)] OrganizationUser savingUser,
|
||||
SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
organization.PlanType = PlanType.EnterpriseAnnually;
|
||||
InviteUserHelper_ArrangeValidPermissions(organization, savingUser, sutProvider);
|
||||
|
||||
// Set up some invites to grant access to SM
|
||||
|
@ -273,8 +273,8 @@ public class CoreHelpersTests
|
||||
{ "sstamp", user.SecurityStamp },
|
||||
}.ToList();
|
||||
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, Array.Empty<CurrentContentOrganization>(),
|
||||
Array.Empty<CurrentContentProvider>(), isPremium);
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, Array.Empty<CurrentContextOrganization>(),
|
||||
Array.Empty<CurrentContextProvider>(), isPremium);
|
||||
|
||||
foreach (var claim in expected)
|
||||
{
|
||||
@ -289,23 +289,23 @@ public class CoreHelpersTests
|
||||
var fixture = new Fixture().WithAutoNSubstitutions();
|
||||
foreach (var organizationUserType in Enum.GetValues<OrganizationUserType>().Except(new[] { OrganizationUserType.Custom }))
|
||||
{
|
||||
var org = fixture.Create<CurrentContentOrganization>();
|
||||
var org = fixture.Create<CurrentContextOrganization>();
|
||||
org.Type = organizationUserType;
|
||||
|
||||
var expected = new KeyValuePair<string, string>($"org{organizationUserType.ToString().ToLower()}", org.Id.ToString());
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, new[] { org }, Array.Empty<CurrentContentProvider>(), false);
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, new[] { org }, Array.Empty<CurrentContextProvider>(), false);
|
||||
|
||||
Assert.Contains(expected, actual);
|
||||
}
|
||||
}
|
||||
|
||||
[Theory, BitAutoData, UserCustomize]
|
||||
public void BuildIdentityClaims_CustomOrganizationUserClaims_Success(User user, CurrentContentOrganization org)
|
||||
public void BuildIdentityClaims_CustomOrganizationUserClaims_Success(User user, CurrentContextOrganization org)
|
||||
{
|
||||
var fixture = new Fixture().WithAutoNSubstitutions();
|
||||
org.Type = OrganizationUserType.Custom;
|
||||
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, new[] { org }, Array.Empty<CurrentContentProvider>(), false);
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, new[] { org }, Array.Empty<CurrentContextProvider>(), false);
|
||||
foreach (var (permitted, claimName) in org.Permissions.ClaimsMap)
|
||||
{
|
||||
var claim = new KeyValuePair<string, string>(claimName, org.Id.ToString());
|
||||
@ -325,10 +325,10 @@ public class CoreHelpersTests
|
||||
public void BuildIdentityClaims_ProviderClaims_Success(User user)
|
||||
{
|
||||
var fixture = new Fixture().WithAutoNSubstitutions();
|
||||
var providers = new List<CurrentContentProvider>();
|
||||
var providers = new List<CurrentContextProvider>();
|
||||
foreach (var providerUserType in Enum.GetValues<ProviderUserType>())
|
||||
{
|
||||
var provider = fixture.Create<CurrentContentProvider>();
|
||||
var provider = fixture.Create<CurrentContextProvider>();
|
||||
provider.Type = providerUserType;
|
||||
providers.Add(provider);
|
||||
}
|
||||
@ -357,7 +357,7 @@ public class CoreHelpersTests
|
||||
}
|
||||
}
|
||||
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, Array.Empty<CurrentContentOrganization>(), providers, false);
|
||||
var actual = CoreHelpers.BuildIdentityClaims(user, Array.Empty<CurrentContextOrganization>(), providers, false);
|
||||
foreach (var claim in claims)
|
||||
{
|
||||
Assert.Contains(claim, actual);
|
||||
@ -416,4 +416,25 @@ public class CoreHelpersTests
|
||||
{
|
||||
Assert.Equal(expected, CoreHelpers.ObfuscateEmail(input));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("user@example.com")]
|
||||
[InlineData("user@example.com ")]
|
||||
[InlineData("user.name@example.com")]
|
||||
public void GetEmailDomain_Success(string email)
|
||||
{
|
||||
Assert.Equal("example.com", CoreHelpers.GetEmailDomain(email));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("")]
|
||||
[InlineData(null)]
|
||||
[InlineData("userexample.com")]
|
||||
[InlineData("user@")]
|
||||
[InlineData("@example.com")]
|
||||
[InlineData("user@ex@ample.com")]
|
||||
public void GetEmailDomain_ReturnsNull(string wrongEmail)
|
||||
{
|
||||
Assert.Null(CoreHelpers.GetEmailDomain(wrongEmail));
|
||||
}
|
||||
}
|
||||
|
@ -530,6 +530,7 @@ public class IdentityServerSsoTests
|
||||
var organization = await organizationRepository.CreateAsync(new Organization
|
||||
{
|
||||
Name = "Test Org",
|
||||
UsePolicies = true
|
||||
});
|
||||
|
||||
var organizationUserRepository = factory.Services.GetRequiredService<IOrganizationUserRepository>();
|
||||
|
@ -556,7 +556,7 @@ public class IdentityServerTests : IClassFixture<IdentityApplicationFactory>
|
||||
var organizationUserRepository = _factory.Services.GetService<IOrganizationUserRepository>();
|
||||
var policyRepository = _factory.Services.GetService<IPolicyRepository>();
|
||||
|
||||
var organization = new Bit.Core.Entities.Organization { Id = organizationId, Enabled = true, UseSso = ssoPolicyEnabled };
|
||||
var organization = new Bit.Core.Entities.Organization { Id = organizationId, Enabled = true, UseSso = ssoPolicyEnabled, UsePolicies = true };
|
||||
await organizationRepository.CreateAsync(organization);
|
||||
|
||||
var user = await userRepository.GetByEmailAsync(username);
|
||||
|
Reference in New Issue
Block a user