1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-02 16:42:50 -05:00

[AC-2027] Update Flexible Collections logic to use organization property (#3644)

* Update optionality to use org.FlexibleCollections

Also break old feature flag key to ensure it's never enabled

* Add logic to set defaults for collection management setting

* Update optionality logic to use org property

* Add comments

* Add helper method for getting individual orgAbility

* Fix validate user update permissions interface

* Fix tests

* dotnet format

* Fix more tests

* Simplify self-hosted update logic

* Fix mapping

* Use new getOrganizationAbility method

* Refactor invite and save orgUser methods

Pass in whole organization object instead of using OrganizationAbility

* fix CipherService tests

* dotnet format

* Remove manager check to simplify this set of changes

* Misc cleanup before review

* Fix undefined variable

* Refactor bulk-access endpoint to avoid early repo call

* Restore manager check

* Add tests for UpdateOrganizationLicenseCommand

* Add nullable regions

* Delete unused dependency

* dotnet format

* Fix test
This commit is contained in:
Thomas Rittson
2024-01-17 22:33:35 +10:00
committed by GitHub
parent ef37cdc71a
commit 96f9fbb951
27 changed files with 472 additions and 411 deletions

View File

@ -65,8 +65,6 @@ public class OrganizationService : IOrganizationService
private readonly IDataProtectorTokenFactory<OrgUserInviteTokenable> _orgUserInviteTokenDataFactory;
private readonly IFeatureService _featureService;
private bool FlexibleCollectionsIsEnabled => _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
public OrganizationService(
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
@ -418,6 +416,9 @@ public class OrganizationService : IOrganizationService
}
}
/// <summary>
/// Create a new organization in a cloud environment
/// </summary>
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(OrganizationSignup signup,
bool provider = false)
{
@ -440,8 +441,9 @@ public class OrganizationService : IOrganizationService
await ValidateSignUpPoliciesAsync(signup.Owner.Id);
}
var flexibleCollectionsIsEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
var flexibleCollectionsSignupEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollectionsSignup, _currentContext);
var flexibleCollectionsV1IsEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1, _currentContext);
@ -482,7 +484,15 @@ public class OrganizationService : IOrganizationService
Status = OrganizationStatusType.Created,
UsePasswordManager = true,
UseSecretsManager = signup.UseSecretsManager,
LimitCollectionCreationDeletion = !flexibleCollectionsIsEnabled,
// This feature flag indicates that new organizations should be automatically onboarded to
// Flexible Collections enhancements
FlexibleCollections = flexibleCollectionsSignupEnabled,
// These collection management settings smooth the migration for existing organizations by disabling some FC behavior.
// If the organization is onboarded to Flexible Collections on signup, we turn them OFF to enable all new behaviour.
// If the organization is NOT onboarded now, they will have to be migrated later, so they default to ON to limit FC changes on migration.
LimitCollectionCreationDeletion = !flexibleCollectionsSignupEnabled,
AllowAdminAccessToAllCollectionItems = !flexibleCollectionsV1IsEnabled
};
@ -534,6 +544,9 @@ public class OrganizationService : IOrganizationService
}
}
/// <summary>
/// Create a new organization on a self-hosted instance
/// </summary>
public async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(
OrganizationLicense license, User owner, string ownerKey, string collectionName, string publicKey,
string privateKey)
@ -558,10 +571,8 @@ public class OrganizationService : IOrganizationService
await ValidateSignUpPoliciesAsync(owner.Id);
var flexibleCollectionsMvpIsEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
var flexibleCollectionsV1IsEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1, _currentContext);
var flexibleCollectionsSignupEnabled =
_featureService.IsEnabled(FeatureFlagKeys.FlexibleCollectionsSignup, _currentContext);
var organization = new Organization
{
@ -603,8 +614,12 @@ public class OrganizationService : IOrganizationService
UseSecretsManager = license.UseSecretsManager,
SmSeats = license.SmSeats,
SmServiceAccounts = license.SmServiceAccounts,
LimitCollectionCreationDeletion = !flexibleCollectionsMvpIsEnabled || license.LimitCollectionCreationDeletion,
AllowAdminAccessToAllCollectionItems = !flexibleCollectionsV1IsEnabled || license.AllowAdminAccessToAllCollectionItems
LimitCollectionCreationDeletion = license.LimitCollectionCreationDeletion,
AllowAdminAccessToAllCollectionItems = license.AllowAdminAccessToAllCollectionItems,
// This feature flag indicates that new organizations should be automatically onboarded to
// Flexible Collections enhancements
FlexibleCollections = flexibleCollectionsSignupEnabled,
};
var result = await SignUpAsync(organization, owner.Id, ownerKey, collectionName, false);
@ -616,6 +631,10 @@ public class OrganizationService : IOrganizationService
return result;
}
/// <summary>
/// Private helper method to create a new organization.
/// This is common code used by both the cloud and self-hosted methods.
/// </summary>
private async Task<Tuple<Organization, OrganizationUser>> SignUpAsync(Organization organization,
Guid ownerId, string ownerKey, string collectionName, bool withPayment)
{
@ -829,6 +848,7 @@ public class OrganizationService : IOrganizationService
{
var inviteTypes = new HashSet<OrganizationUserType>(invites.Where(i => i.invite.Type.HasValue)
.Select(i => i.invite.Type.Value));
if (invitingUserId.HasValue && inviteTypes.Count > 0)
{
foreach (var (invite, _) in invites)
@ -2008,7 +2028,11 @@ public class OrganizationService : IOrganizationService
throw new BadRequestException("Custom users can only grant the same custom permissions that they have.");
}
if (FlexibleCollectionsIsEnabled && newType == OrganizationUserType.Manager && oldType is not OrganizationUserType.Manager)
// TODO: pass in the whole organization object when this is refactored into a command/query
// See AC-2036
var organizationAbility = await _applicationCacheService.GetOrganizationAbilityAsync(organizationId);
var flexibleCollectionsEnabled = organizationAbility?.FlexibleCollections ?? false;
if (flexibleCollectionsEnabled && newType == OrganizationUserType.Manager && oldType is not OrganizationUserType.Manager)
{
throw new BadRequestException("Manager role is deprecated after Flexible Collections.");
}