1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 07:36:14 -05:00

[AC-2052] Block Manager role and AccessAll if using FlexibleCollections (#3671)

* Also don't assign AccessAll to the first orgUser if using Flexible Collections
This commit is contained in:
Thomas Rittson
2024-01-22 08:56:20 +10:00
committed by GitHub
parent 4b6299a055
commit 77698c3ee2
9 changed files with 291 additions and 63 deletions

View File

@ -251,6 +251,64 @@ public class OrganizationServiceTests
);
}
[Theory]
[BitAutoData(PlanType.FamiliesAnnually)]
public async Task SignUp_WithFlexibleCollections_SetsAccessAllToFalse
(PlanType planType, OrganizationSignup signup, SutProvider<OrganizationService> sutProvider)
{
signup.Plan = planType;
var plan = StaticStore.GetPlan(signup.Plan);
signup.AdditionalSeats = 0;
signup.PaymentMethodType = PaymentMethodType.Card;
signup.PremiumAccessAddon = false;
signup.UseSecretsManager = false;
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.FlexibleCollectionsSignup)
.Returns(true);
var result = await sutProvider.Sut.SignUpAsync(signup);
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).CreateAsync(
Arg.Is<OrganizationUser>(o =>
o.UserId == signup.Owner.Id &&
o.AccessAll == false));
Assert.NotNull(result);
Assert.NotNull(result.Item1);
Assert.NotNull(result.Item2);
Assert.IsType<Tuple<Organization, OrganizationUser>>(result);
}
[Theory]
[BitAutoData(PlanType.FamiliesAnnually)]
public async Task SignUp_WithoutFlexibleCollections_SetsAccessAllToTrue
(PlanType planType, OrganizationSignup signup, SutProvider<OrganizationService> sutProvider)
{
signup.Plan = planType;
var plan = StaticStore.GetPlan(signup.Plan);
signup.AdditionalSeats = 0;
signup.PaymentMethodType = PaymentMethodType.Card;
signup.PremiumAccessAddon = false;
signup.UseSecretsManager = false;
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.FlexibleCollectionsSignup)
.Returns(false);
var result = await sutProvider.Sut.SignUpAsync(signup);
await sutProvider.GetDependency<IOrganizationUserRepository>().Received(1).CreateAsync(
Arg.Is<OrganizationUser>(o =>
o.UserId == signup.Owner.Id &&
o.AccessAll == true));
Assert.NotNull(result);
Assert.NotNull(result.Item1);
Assert.NotNull(result.Item2);
Assert.IsType<Tuple<Organization, OrganizationUser>>(result);
}
[Theory]
[BitAutoData(PlanType.EnterpriseAnnually)]
[BitAutoData(PlanType.EnterpriseMonthly)]
@ -378,7 +436,7 @@ public class OrganizationServiceTests
[Theory]
[OrganizationInviteCustomize(InviteeUserType = OrganizationUserType.User,
InvitorUserType = OrganizationUserType.Owner), BitAutoData]
InvitorUserType = OrganizationUserType.Owner), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_NoEmails_Throws(Organization organization, OrganizationUser invitor,
OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
{
@ -391,7 +449,7 @@ public class OrganizationServiceTests
}
[Theory]
[OrganizationInviteCustomize, BitAutoData]
[OrganizationInviteCustomize, OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_DuplicateEmails_PassesWithoutDuplicates(Organization organization, OrganizationUser invitor,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser owner,
OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
@ -434,7 +492,7 @@ public class OrganizationServiceTests
}
[Theory]
[OrganizationInviteCustomize, BitAutoData]
[OrganizationInviteCustomize, OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_SsoOrgWithNullSsoConfig_Passes(Organization organization, OrganizationUser invitor,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser owner,
OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
@ -483,7 +541,7 @@ public class OrganizationServiceTests
}
[Theory]
[OrganizationInviteCustomize, BitAutoData]
[OrganizationInviteCustomize, OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_SsoOrgWithNeverEnabledRequireSsoPolicy_Passes(Organization organization, SsoConfig ssoConfig, OrganizationUser invitor,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser owner,
OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
@ -537,7 +595,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Admin,
InvitorUserType = OrganizationUserType.Owner
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_NoOwner_Throws(Organization organization, OrganizationUser invitor,
OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
{
@ -553,7 +611,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Owner,
InvitorUserType = OrganizationUserType.Admin
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_NonOwnerConfiguringOwner_Throws(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -572,7 +630,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Custom,
InvitorUserType = OrganizationUserType.User
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_NonAdminConfiguringAdmin_Throws(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -593,7 +651,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Custom,
InvitorUserType = OrganizationUserType.Admin
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_WithCustomType_WhenUseCustomPermissionsIsFalse_Throws(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -620,7 +678,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Custom,
InvitorUserType = OrganizationUserType.Admin
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_WithCustomType_WhenUseCustomPermissionsIsTrue_Passes(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -646,6 +704,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
}
[Theory]
[OrganizationCustomize(FlexibleCollections = false)]
[BitAutoData(OrganizationUserType.Admin)]
[BitAutoData(OrganizationUserType.Manager)]
[BitAutoData(OrganizationUserType.Owner)]
@ -679,7 +738,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Manager,
InvitorUserType = OrganizationUserType.Custom
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_CustomUserWithoutManageUsersConfiguringUser_Throws(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -707,7 +766,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.Admin,
InvitorUserType = OrganizationUserType.Custom
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_CustomUserConfiguringAdmin_Throws(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -733,7 +792,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.User,
InvitorUserType = OrganizationUserType.Owner
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_NoPermissionsObject_Passes(Organization organization, OrganizationUserInvite invite,
OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
@ -759,7 +818,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.User,
InvitorUserType = OrganizationUserType.Custom
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_Passes(Organization organization, IEnumerable<(OrganizationUserInvite invite, string externalId)> invites,
OrganizationUser invitor,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser owner,
@ -832,7 +891,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
[OrganizationInviteCustomize(
InviteeUserType = OrganizationUserType.User,
InvitorUserType = OrganizationUserType.Custom
), BitAutoData]
), OrganizationCustomize(FlexibleCollections = false), BitAutoData]
public async Task InviteUser_WithEventSystemUser_Passes(Organization organization, EventSystemUser eventSystemUser, IEnumerable<(OrganizationUserInvite invite, string externalId)> invites,
OrganizationUser invitor,
[OrganizationUser(OrganizationUserStatusType.Confirmed, OrganizationUserType.Owner)] OrganizationUser owner,
@ -882,7 +941,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
await sutProvider.GetDependency<IEventService>().Received(1).LogOrganizationUserEventsAsync(Arg.Any<IEnumerable<(OrganizationUser, EventType, EventSystemUser, DateTime?)>>());
}
[Theory, BitAutoData, OrganizationInviteCustomize]
[Theory, BitAutoData, OrganizationCustomize(FlexibleCollections = false), OrganizationInviteCustomize]
public async Task InviteUser_WithSecretsManager_Passes(Organization organization,
IEnumerable<(OrganizationUserInvite invite, string externalId)> invites,
OrganizationUser savingUser, SutProvider<OrganizationService> sutProvider)
@ -916,7 +975,7 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
!update.MaxAutoscaleSmSeatsChanged));
}
[Theory, BitAutoData, OrganizationInviteCustomize]
[Theory, BitAutoData, OrganizationCustomize(FlexibleCollections = false), OrganizationInviteCustomize]
public async Task InviteUser_WithSecretsManager_WhenErrorIsThrown_RevertsAutoscaling(Organization organization,
IEnumerable<(OrganizationUserInvite invite, string externalId)> invites,
OrganizationUser savingUser, SutProvider<OrganizationService> sutProvider)
@ -972,26 +1031,48 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
});
}
[Theory, BitAutoData]
public async Task InviteUser_WithFCEnabled_WhenInvitingManager_Throws(OrganizationAbility organizationAbility,
[Theory, OrganizationCustomize(FlexibleCollections = true), BitAutoData]
public async Task InviteUser_WithFlexibleCollections_WhenInvitingManager_Throws(Organization organization,
OrganizationUserInvite invite, OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
invite.Type = OrganizationUserType.Manager;
organizationAbility.FlexibleCollections = true;
organization.FlexibleCollections = true;
sutProvider.GetDependency<IApplicationCacheService>()
.GetOrganizationAbilityAsync(organizationAbility.Id)
.Returns(organizationAbility);
sutProvider.GetDependency<IOrganizationRepository>()
.GetByIdAsync(organization.Id)
.Returns(organization);
sutProvider.GetDependency<ICurrentContext>()
.ManageUsers(organizationAbility.Id)
.ManageUsers(organization.Id)
.Returns(true);
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.InviteUsersAsync(organizationAbility.Id, invitor.UserId,
() => sutProvider.Sut.InviteUsersAsync(organization.Id, invitor.UserId,
new (OrganizationUserInvite, string)[] { (invite, null) }));
Assert.Contains("manager role is deprecated", exception.Message.ToLowerInvariant());
Assert.Contains("manager role has been deprecated", exception.Message.ToLowerInvariant());
}
[Theory, OrganizationCustomize(FlexibleCollections = true), BitAutoData]
public async Task InviteUser_WithFlexibleCollections_WithAccessAll_Throws(Organization organization,
OrganizationUserInvite invite, OrganizationUser invitor, SutProvider<OrganizationService> sutProvider)
{
invite.Type = OrganizationUserType.User;
invite.AccessAll = true;
sutProvider.GetDependency<IOrganizationRepository>()
.GetByIdAsync(organization.Id)
.Returns(organization);
sutProvider.GetDependency<ICurrentContext>()
.ManageUsers(organization.Id)
.Returns(true);
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.InviteUsersAsync(organization.Id, invitor.UserId,
new (OrganizationUserInvite, string)[] { (invite, null) }));
Assert.Contains("accessall property has been deprecated", exception.Message.ToLowerInvariant());
}
private void InviteUserHelper_ArrangeValidPermissions(Organization organization, OrganizationUser savingUser,
@ -1275,15 +1356,21 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
}
[Theory, BitAutoData]
public async Task SaveUser_WithFCEnabled_WhenUpgradingToManager_Throws(
public async Task SaveUser_WithFlexibleCollections_WhenUpgradingToManager_Throws(
OrganizationAbility organizationAbility,
[OrganizationUser(type: OrganizationUserType.User)] OrganizationUser oldUserData,
[OrganizationUser(type: OrganizationUserType.Manager)] OrganizationUser newUserData,
[OrganizationUser(type: OrganizationUserType.Owner, status: OrganizationUserStatusType.Confirmed)] OrganizationUser savingUser,
IEnumerable<CollectionAccessSelection> collections,
IEnumerable<Guid> groups,
SutProvider<OrganizationService> sutProvider)
{
organizationAbility.FlexibleCollections = true;
newUserData.Id = oldUserData.Id;
newUserData.UserId = oldUserData.UserId;
newUserData.OrganizationId = oldUserData.OrganizationId = savingUser.OrganizationId = organizationAbility.Id;
newUserData.Permissions = CoreHelpers.ClassToJsonData(new Permissions());
sutProvider.GetDependency<IApplicationCacheService>()
.GetOrganizationAbilityAsync(organizationAbility.Id)
.Returns(organizationAbility);
@ -1296,15 +1383,53 @@ OrganizationUserInvite invite, SutProvider<OrganizationService> sutProvider)
.GetByIdAsync(oldUserData.Id)
.Returns(oldUserData);
newUserData.Id = oldUserData.Id;
newUserData.UserId = oldUserData.UserId;
newUserData.OrganizationId = oldUserData.OrganizationId = organizationAbility.Id;
newUserData.Permissions = CoreHelpers.ClassToJsonData(new Permissions());
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByOrganizationAsync(organizationAbility.Id, OrganizationUserType.Owner)
.Returns(new List<OrganizationUser> { savingUser });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveUserAsync(newUserData, oldUserData.UserId, collections, groups));
Assert.Contains("manager role is deprecated", exception.Message.ToLowerInvariant());
Assert.Contains("manager role has been deprecated", exception.Message.ToLowerInvariant());
}
[Theory, BitAutoData]
public async Task SaveUser_WithFlexibleCollections_WithAccessAll_Throws(
OrganizationAbility organizationAbility,
[OrganizationUser(type: OrganizationUserType.User)] OrganizationUser oldUserData,
[OrganizationUser(type: OrganizationUserType.User)] OrganizationUser newUserData,
[OrganizationUser(type: OrganizationUserType.Owner, status: OrganizationUserStatusType.Confirmed)] OrganizationUser savingUser,
IEnumerable<CollectionAccessSelection> collections,
IEnumerable<Guid> groups,
SutProvider<OrganizationService> sutProvider)
{
organizationAbility.FlexibleCollections = true;
newUserData.Id = oldUserData.Id;
newUserData.UserId = oldUserData.UserId;
newUserData.OrganizationId = oldUserData.OrganizationId = savingUser.OrganizationId = organizationAbility.Id;
newUserData.Permissions = CoreHelpers.ClassToJsonData(new Permissions());
newUserData.AccessAll = true;
sutProvider.GetDependency<IApplicationCacheService>()
.GetOrganizationAbilityAsync(organizationAbility.Id)
.Returns(organizationAbility);
sutProvider.GetDependency<ICurrentContext>()
.ManageUsers(organizationAbility.Id)
.Returns(true);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetByIdAsync(oldUserData.Id)
.Returns(oldUserData);
sutProvider.GetDependency<IOrganizationUserRepository>()
.GetManyByOrganizationAsync(organizationAbility.Id, OrganizationUserType.Owner)
.Returns(new List<OrganizationUser> { savingUser });
var exception = await Assert.ThrowsAsync<BadRequestException>(
() => sutProvider.Sut.SaveUserAsync(newUserData, oldUserData.UserId, collections, groups));
Assert.Contains("the accessall property has been deprecated", exception.Message.ToLowerInvariant());
}
[Theory, BitAutoData]