mirror of
https://github.com/bitwarden/server
synced 2025-12-06 00:03:34 +00:00
[PM-21752] Add granular events for collection management settings (#6269)
* Add new event types for collection management settings in EventType enum * Refactor collection management settings update process in OrganizationsController and IOrganizationService. Introduced UpdateCollectionManagementSettingsAsync method to streamline updates and logging for collection management settings. * Add unit tests for collection management settings updates in OrganizationsController and OrganizationService. Implemented tests to verify the successful update of collection management settings and the logging of specific events when settings are changed. Added error handling for cases where the organization is not found. * Refactor collection management settings handling in OrganizationsController and IOrganizationService. Updated the UpdateCollectionManagementSettingsAsync method to accept a single settings object, simplifying the parameter list and improving code readability. Introduced a new OrganizationCollectionManagementSettings model to encapsulate collection management settings. Adjusted related tests to reflect these changes. * Add Obsolete attribute to Organization_CollectionManagement_Updated event in EventType enum
This commit is contained in:
@@ -2,10 +2,12 @@
|
||||
using AutoFixture.Xunit2;
|
||||
using Bit.Api.AdminConsole.Controllers;
|
||||
using Bit.Api.Auth.Models.Request.Accounts;
|
||||
using Bit.Api.Models.Request.Organizations;
|
||||
using Bit.Core;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.Models.Business;
|
||||
using Bit.Core.AdminConsole.Models.Business.Tokenables;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationApiKeys.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Organizations;
|
||||
@@ -29,6 +31,7 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Tokens;
|
||||
using Bit.Core.Utilities;
|
||||
using Bit.Infrastructure.EntityFramework.AdminConsole.Models.Provider;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
@@ -293,4 +296,40 @@ public class OrganizationsControllerTests : IDisposable
|
||||
|
||||
Assert.True(result.ResetPasswordEnabled);
|
||||
}
|
||||
|
||||
[Theory, AutoData]
|
||||
public async Task PutCollectionManagement_ValidRequest_Success(
|
||||
Organization organization,
|
||||
OrganizationCollectionManagementUpdateRequestModel model)
|
||||
{
|
||||
// Arrange
|
||||
_currentContext.OrganizationOwner(organization.Id).Returns(true);
|
||||
|
||||
var plan = StaticStore.GetPlan(PlanType.EnterpriseAnnually);
|
||||
_pricingClient.GetPlan(Arg.Any<PlanType>()).Returns(plan);
|
||||
|
||||
_organizationService
|
||||
.UpdateCollectionManagementSettingsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<OrganizationCollectionManagementSettings>(s =>
|
||||
s.LimitCollectionCreation == model.LimitCollectionCreation &&
|
||||
s.LimitCollectionDeletion == model.LimitCollectionDeletion &&
|
||||
s.LimitItemDeletion == model.LimitItemDeletion &&
|
||||
s.AllowAdminAccessToAllCollectionItems == model.AllowAdminAccessToAllCollectionItems))
|
||||
.Returns(organization);
|
||||
|
||||
// Act
|
||||
await _sut.PutCollectionManagement(organization.Id, model);
|
||||
|
||||
// Assert
|
||||
await _organizationService
|
||||
.Received(1)
|
||||
.UpdateCollectionManagementSettingsAsync(
|
||||
organization.Id,
|
||||
Arg.Is<OrganizationCollectionManagementSettings>(s =>
|
||||
s.LimitCollectionCreation == model.LimitCollectionCreation &&
|
||||
s.LimitCollectionDeletion == model.LimitCollectionDeletion &&
|
||||
s.LimitItemDeletion == model.LimitItemDeletion &&
|
||||
s.AllowAdminAccessToAllCollectionItems == model.AllowAdminAccessToAllCollectionItems));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities.Provider;
|
||||
using Bit.Core.AdminConsole.Enums.Provider;
|
||||
using Bit.Core.AdminConsole.Models.Business;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.Interfaces;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.OrganizationUsers.InviteUsers.Models;
|
||||
@@ -27,7 +28,6 @@ using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Bit.Test.Common.Fakes;
|
||||
using NSubstitute;
|
||||
using NSubstitute.ExceptionExtensions;
|
||||
using NSubstitute.ReceivedExtensions;
|
||||
using NSubstitute.ReturnsExtensions;
|
||||
using Stripe;
|
||||
using Xunit;
|
||||
@@ -42,8 +42,6 @@ public class OrganizationServiceTests
|
||||
{
|
||||
private readonly IDataProtectorTokenFactory<OrgUserInviteTokenable> _orgUserInviteTokenDataFactory = new FakeDataProtectorTokenFactory<OrgUserInviteTokenable>();
|
||||
|
||||
|
||||
|
||||
[Theory]
|
||||
[OrganizationInviteCustomize(InviteeUserType = OrganizationUserType.User,
|
||||
InvitorUserType = OrganizationUserType.Owner), OrganizationCustomize, BitAutoData]
|
||||
@@ -1229,6 +1227,109 @@ public class OrganizationServiceTests
|
||||
.GetByIdentifierAsync(Arg.Is<string>(id => id == organization.Identifier));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData(false, true, false, true)]
|
||||
[BitAutoData(true, false, true, false)]
|
||||
public async Task UpdateCollectionManagementSettingsAsync_WhenSettingsChanged_LogsSpecificEvents(
|
||||
bool newLimitCollectionCreation,
|
||||
bool newLimitCollectionDeletion,
|
||||
bool newLimitItemDeletion,
|
||||
bool newAllowAdminAccessToAllCollectionItems,
|
||||
Organization existingOrganization, SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
existingOrganization.LimitCollectionCreation = false;
|
||||
existingOrganization.LimitCollectionDeletion = false;
|
||||
existingOrganization.LimitItemDeletion = false;
|
||||
existingOrganization.AllowAdminAccessToAllCollectionItems = false;
|
||||
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(existingOrganization.Id)
|
||||
.Returns(existingOrganization);
|
||||
|
||||
var settings = new OrganizationCollectionManagementSettings
|
||||
{
|
||||
LimitCollectionCreation = newLimitCollectionCreation,
|
||||
LimitCollectionDeletion = newLimitCollectionDeletion,
|
||||
LimitItemDeletion = newLimitItemDeletion,
|
||||
AllowAdminAccessToAllCollectionItems = newAllowAdminAccessToAllCollectionItems
|
||||
};
|
||||
|
||||
// Act
|
||||
await sutProvider.Sut.UpdateCollectionManagementSettingsAsync(existingOrganization.Id, settings);
|
||||
|
||||
// Assert
|
||||
var eventService = sutProvider.GetDependency<IEventService>();
|
||||
if (newLimitCollectionCreation)
|
||||
{
|
||||
await eventService.Received(1).LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_LimitCollectionCreationEnabled));
|
||||
}
|
||||
else
|
||||
{
|
||||
await eventService.DidNotReceive().LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_LimitCollectionCreationEnabled));
|
||||
}
|
||||
|
||||
if (newLimitCollectionDeletion)
|
||||
{
|
||||
await eventService.Received(1).LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_LimitCollectionDeletionEnabled));
|
||||
}
|
||||
else
|
||||
{
|
||||
await eventService.DidNotReceive().LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_LimitCollectionDeletionEnabled));
|
||||
}
|
||||
|
||||
if (newLimitItemDeletion)
|
||||
{
|
||||
await eventService.Received(1).LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_LimitItemDeletionEnabled));
|
||||
}
|
||||
else
|
||||
{
|
||||
await eventService.DidNotReceive().LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_LimitItemDeletionEnabled));
|
||||
}
|
||||
|
||||
if (newAllowAdminAccessToAllCollectionItems)
|
||||
{
|
||||
await eventService.Received(1).LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled));
|
||||
}
|
||||
else
|
||||
{
|
||||
await eventService.DidNotReceive().LogOrganizationEventAsync(
|
||||
Arg.Is<Organization>(org => org.Id == existingOrganization.Id),
|
||||
Arg.Is<EventType>(e => e == EventType.Organization_CollectionManagement_AllowAdminAccessToAllCollectionItemsEnabled));
|
||||
}
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task UpdateCollectionManagementSettingsAsync_WhenOrganizationNotFound_ThrowsNotFoundException(
|
||||
Guid organizationId, OrganizationCollectionManagementSettings settings, SutProvider<OrganizationService> sutProvider)
|
||||
{
|
||||
// Arrange
|
||||
sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.GetByIdAsync(organizationId)
|
||||
.Returns((Organization)null);
|
||||
|
||||
// Act/Assert
|
||||
await Assert.ThrowsAsync<NotFoundException>(() => sutProvider.Sut.UpdateCollectionManagementSettingsAsync(organizationId, settings));
|
||||
|
||||
await sutProvider.GetDependency<IOrganizationRepository>()
|
||||
.Received(1)
|
||||
.GetByIdAsync(organizationId);
|
||||
}
|
||||
|
||||
// Must set real guids in order for dictionary of guids to not throw aggregate exceptions
|
||||
private void SetupOrgUserRepositoryCreateManyAsyncMock(IOrganizationUserRepository organizationUserRepository)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user