1
0
mirror of https://github.com/bitwarden/server.git synced 2025-06-30 23:52: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

@ -3,7 +3,6 @@ using Bit.Api.AdminConsole.Models.Response;
using Bit.Api.Models.Response;
using Bit.Api.Utilities;
using Bit.Api.Vault.AuthorizationHandlers.Groups;
using Bit.Core;
using Bit.Core.AdminConsole.OrganizationFeatures.Groups.Interfaces;
using Bit.Core.AdminConsole.Repositories;
using Bit.Core.AdminConsole.Services;
@ -27,10 +26,8 @@ public class GroupsController : Controller
private readonly ICurrentContext _currentContext;
private readonly ICreateGroupCommand _createGroupCommand;
private readonly IUpdateGroupCommand _updateGroupCommand;
private readonly IFeatureService _featureService;
private readonly IAuthorizationService _authorizationService;
private bool UseFlexibleCollections => _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
private readonly IApplicationCacheService _applicationCacheService;
public GroupsController(
IGroupRepository groupRepository,
@ -41,7 +38,8 @@ public class GroupsController : Controller
IUpdateGroupCommand updateGroupCommand,
IDeleteGroupCommand deleteGroupCommand,
IFeatureService featureService,
IAuthorizationService authorizationService)
IAuthorizationService authorizationService,
IApplicationCacheService applicationCacheService)
{
_groupRepository = groupRepository;
_groupService = groupService;
@ -50,8 +48,8 @@ public class GroupsController : Controller
_createGroupCommand = createGroupCommand;
_updateGroupCommand = updateGroupCommand;
_deleteGroupCommand = deleteGroupCommand;
_featureService = featureService;
_authorizationService = authorizationService;
_applicationCacheService = applicationCacheService;
}
[HttpGet("{id}")]
@ -81,7 +79,7 @@ public class GroupsController : Controller
[HttpGet("")]
public async Task<ListResponseModel<GroupDetailsResponseModel>> Get(Guid orgId)
{
if (UseFlexibleCollections)
if (await FlexibleCollectionsIsEnabledAsync(orgId))
{
// New flexible collections logic
return await Get_vNext(orgId);
@ -217,4 +215,10 @@ public class GroupsController : Controller
var responses = groups.Select(g => new GroupDetailsResponseModel(g.Item1, g.Item2));
return new ListResponseModel<GroupDetailsResponseModel>(responses);
}
private async Task<bool> FlexibleCollectionsIsEnabledAsync(Guid organizationId)
{
var organizationAbility = await _applicationCacheService.GetOrganizationAbilityAsync(organizationId);
return organizationAbility?.FlexibleCollections ?? false;
}
}

View File

@ -4,7 +4,6 @@ using Bit.Api.Models.Request.Organizations;
using Bit.Api.Models.Response;
using Bit.Api.Utilities;
using Bit.Api.Vault.AuthorizationHandlers.OrganizationUsers;
using Bit.Core;
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
@ -39,10 +38,8 @@ public class OrganizationUsersController : Controller
private readonly IUpdateSecretsManagerSubscriptionCommand _updateSecretsManagerSubscriptionCommand;
private readonly IUpdateOrganizationUserGroupsCommand _updateOrganizationUserGroupsCommand;
private readonly IAcceptOrgUserCommand _acceptOrgUserCommand;
private readonly IFeatureService _featureService;
private readonly IAuthorizationService _authorizationService;
private bool UseFlexibleCollections => _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollections, _currentContext);
private readonly IApplicationCacheService _applicationCacheService;
public OrganizationUsersController(
IOrganizationRepository organizationRepository,
@ -57,8 +54,8 @@ public class OrganizationUsersController : Controller
IUpdateSecretsManagerSubscriptionCommand updateSecretsManagerSubscriptionCommand,
IUpdateOrganizationUserGroupsCommand updateOrganizationUserGroupsCommand,
IAcceptOrgUserCommand acceptOrgUserCommand,
IFeatureService featureService,
IAuthorizationService authorizationService)
IAuthorizationService authorizationService,
IApplicationCacheService applicationCacheService)
{
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
@ -72,8 +69,8 @@ public class OrganizationUsersController : Controller
_updateSecretsManagerSubscriptionCommand = updateSecretsManagerSubscriptionCommand;
_updateOrganizationUserGroupsCommand = updateOrganizationUserGroupsCommand;
_acceptOrgUserCommand = acceptOrgUserCommand;
_featureService = featureService;
_authorizationService = authorizationService;
_applicationCacheService = applicationCacheService;
}
[HttpGet("{id}")]
@ -98,7 +95,7 @@ public class OrganizationUsersController : Controller
[HttpGet("")]
public async Task<ListResponseModel<OrganizationUserUserDetailsResponseModel>> Get(Guid orgId, bool includeGroups = false, bool includeCollections = false)
{
var authorized = UseFlexibleCollections
var authorized = await FlexibleCollectionsIsEnabledAsync(orgId)
? (await _authorizationService.AuthorizeAsync(User, OrganizationUserOperations.ReadAll(orgId))).Succeeded
: await _currentContext.ViewAllCollections(orgId) ||
await _currentContext.ViewAssignedCollections(orgId) ||
@ -518,4 +515,10 @@ public class OrganizationUsersController : Controller
return new ListResponseModel<OrganizationUserBulkResponseModel>(result.Select(r =>
new OrganizationUserBulkResponseModel(r.Item1.Id, r.Item2)));
}
private async Task<bool> FlexibleCollectionsIsEnabledAsync(Guid organizationId)
{
var organizationAbility = await _applicationCacheService.GetOrganizationAbilityAsync(organizationId);
return organizationAbility?.FlexibleCollections ?? false;
}
}

View File

@ -784,7 +784,6 @@ public class OrganizationsController : Controller
}
[HttpPut("{id}/collection-management")]
[RequireFeature(FeatureFlagKeys.FlexibleCollections)]
[SelfHosted(NotSelfHostedOnly = true)]
public async Task<OrganizationResponseModel> PutCollectionManagement(Guid id, [FromBody] OrganizationCollectionManagementUpdateRequestModel model)
{
@ -799,6 +798,11 @@ public class OrganizationsController : Controller
throw new NotFoundException();
}
if (!organization.FlexibleCollections)
{
throw new BadRequestException("Organization does not have collection enhancements enabled");
}
var v1Enabled = _featureService.IsEnabled(FeatureFlagKeys.FlexibleCollectionsV1, _currentContext);
if (!v1Enabled)