mirror of
https://github.com/bitwarden/server.git
synced 2025-07-05 01:52:49 -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:
@ -241,11 +241,13 @@ public class Organization : ITableObject<Guid>, ISubscriber, IStorable, IStorabl
|
||||
return providers[provider];
|
||||
}
|
||||
|
||||
public void UpdateFromLicense(
|
||||
OrganizationLicense license,
|
||||
bool flexibleCollectionsMvpIsEnabled,
|
||||
bool flexibleCollectionsV1IsEnabled)
|
||||
public void UpdateFromLicense(OrganizationLicense license)
|
||||
{
|
||||
// The following properties are intentionally excluded from being updated:
|
||||
// - Id - self-hosted org will have its own unique Guid
|
||||
// - MaxStorageGb - not enforced for self-hosted because we're not providing the storage
|
||||
// - FlexibleCollections - the self-hosted organization must do its own data migration to set this property, it cannot be updated from cloud
|
||||
|
||||
Name = license.Name;
|
||||
BusinessName = license.BusinessName;
|
||||
BillingEmail = license.BillingEmail;
|
||||
@ -275,7 +277,7 @@ public class Organization : ITableObject<Guid>, ISubscriber, IStorable, IStorabl
|
||||
UseSecretsManager = license.UseSecretsManager;
|
||||
SmSeats = license.SmSeats;
|
||||
SmServiceAccounts = license.SmServiceAccounts;
|
||||
LimitCollectionCreationDeletion = !flexibleCollectionsMvpIsEnabled || license.LimitCollectionCreationDeletion;
|
||||
AllowAdminAccessToAllCollectionItems = !flexibleCollectionsV1IsEnabled || license.AllowAdminAccessToAllCollectionItems;
|
||||
LimitCollectionCreationDeletion = license.LimitCollectionCreationDeletion;
|
||||
AllowAdminAccessToAllCollectionItems = license.AllowAdminAccessToAllCollectionItems;
|
||||
}
|
||||
}
|
||||
|
@ -145,7 +145,8 @@ public class SelfHostedOrganizationDetails : Organization
|
||||
MaxAutoscaleSeats = MaxAutoscaleSeats,
|
||||
OwnersNotifiedOfAutoscaling = OwnersNotifiedOfAutoscaling,
|
||||
LimitCollectionCreationDeletion = LimitCollectionCreationDeletion,
|
||||
AllowAdminAccessToAllCollectionItems = AllowAdminAccessToAllCollectionItems
|
||||
AllowAdminAccessToAllCollectionItems = AllowAdminAccessToAllCollectionItems,
|
||||
FlexibleCollections = FlexibleCollections
|
||||
};
|
||||
}
|
||||
}
|
||||
|
@ -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.");
|
||||
}
|
||||
|
Reference in New Issue
Block a user