mirror of
https://github.com/bitwarden/server.git
synced 2025-06-30 07:36:14 -05:00
[PM-18235] Add PersonalOwnershipPolicyRequirement (#5439)
* Add PersonalOwnershipPolicyRequirement for managing personal ownership policy * Add tests for PersonalOwnershipPolicyRequirement * Register PersonalOwnershipPolicyRequirement in policy requirement factory * Update ImportCiphersCommand to check PersonalOwnershipPolicyRequirement if the PolicyRequirements flag is enabled Update unit tests * Update CipherService to support PersonalOwnershipPolicyRequirement with feature flag - Add support for checking personal ownership policy using PolicyRequirementQuery when feature flag is enabled - Update CipherService constructor to inject new dependencies - Add tests for personal vault restrictions with and without feature flag * Clean up redundant "Arrange", "Act", and "Assert" comments in test methods * Refactor PersonalOwnershipPolicyRequirementTests method names for clarity - Improve test method names to better describe their purpose and behavior - Rename methods to follow a more descriptive naming convention - No functional changes to the test logic * Remove commented code explaining policy check * Refactor PersonalOwnership Policy Requirement implementation - Add PersonalOwnershipPolicyRequirementFactory to replace static Create method - Simplify policy requirement creation logic - Update PolicyServiceCollectionExtensions to register new factory - Update ImportCiphersCommand to use correct user ID parameter - Remove redundant PersonalOwnershipPolicyRequirementTests * Remove redundant PersonalOwnershipPolicyRequirementTests * Remove unnecessary tests from PersonalOwnershipPolicyRequirementFactoryTests
This commit is contained in:
@ -0,0 +1,31 @@
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
using Bit.Core.Test.AdminConsole.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture;
|
||||
using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using Xunit;
|
||||
|
||||
namespace Bit.Core.Test.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
|
||||
[SutProviderCustomize]
|
||||
public class PersonalOwnershipPolicyRequirementFactoryTests
|
||||
{
|
||||
[Theory, BitAutoData]
|
||||
public void DisablePersonalOwnership_WithNoPolicies_ReturnsFalse(SutProvider<PersonalOwnershipPolicyRequirementFactory> sutProvider)
|
||||
{
|
||||
var actual = sutProvider.Sut.Create([]);
|
||||
|
||||
Assert.False(actual.DisablePersonalOwnership);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public void DisablePersonalOwnership_WithPersonalOwnershipPolicies_ReturnsTrue(
|
||||
[PolicyDetails(PolicyType.PersonalOwnership)] PolicyDetails[] policies,
|
||||
SutProvider<PersonalOwnershipPolicyRequirementFactory> sutProvider)
|
||||
{
|
||||
var actual = sutProvider.Sut.Create(policies);
|
||||
|
||||
Assert.True(actual.DisablePersonalOwnership);
|
||||
}
|
||||
}
|
@ -1,10 +1,13 @@
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Exceptions;
|
||||
using Bit.Core.Platform.Push;
|
||||
using Bit.Core.Repositories;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core.Test.AutoFixture.CipherFixtures;
|
||||
using Bit.Core.Tools.Enums;
|
||||
using Bit.Core.Tools.ImportFeatures;
|
||||
@ -18,7 +21,6 @@ using Bit.Test.Common.AutoFixture.Attributes;
|
||||
using NSubstitute;
|
||||
using Xunit;
|
||||
|
||||
|
||||
namespace Bit.Core.Test.Tools.ImportFeatures;
|
||||
|
||||
[UserCipherCustomize]
|
||||
@ -51,6 +53,34 @@ public class ImportCiphersAsyncCommandTests
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushSyncVaultAsync(importingUserId);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ImportIntoIndividualVaultAsync_WithPolicyRequirementsEnabled_WithDisablePersonalOwnershipPolicyDisabled_Success(
|
||||
Guid importingUserId,
|
||||
List<CipherDetails> ciphers,
|
||||
SutProvider<ImportCiphersCommand> sutProvider)
|
||||
{
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<PersonalOwnershipPolicyRequirement>(importingUserId)
|
||||
.Returns(new PersonalOwnershipPolicyRequirement { DisablePersonalOwnership = false });
|
||||
|
||||
sutProvider.GetDependency<IFolderRepository>()
|
||||
.GetManyByUserIdAsync(importingUserId)
|
||||
.Returns(new List<Folder>());
|
||||
|
||||
var folders = new List<Folder> { new Folder { UserId = importingUserId } };
|
||||
|
||||
var folderRelationships = new List<KeyValuePair<int, int>>();
|
||||
|
||||
await sutProvider.Sut.ImportIntoIndividualVaultAsync(folders, ciphers, folderRelationships, importingUserId);
|
||||
|
||||
await sutProvider.GetDependency<ICipherRepository>().Received(1).CreateAsync(ciphers, Arg.Any<List<Folder>>());
|
||||
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushSyncVaultAsync(importingUserId);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ImportIntoIndividualVaultAsync_ThrowsBadRequestException(
|
||||
List<Folder> folders,
|
||||
@ -73,6 +103,32 @@ public class ImportCiphersAsyncCommandTests
|
||||
Assert.Equal("You cannot import items into your personal vault because you are a member of an organization which forbids it.", exception.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ImportIntoIndividualVaultAsync_WithPolicyRequirementsEnabled_WithDisablePersonalOwnershipPolicyEnabled_ThrowsBadRequestException(
|
||||
List<Folder> folders,
|
||||
List<CipherDetails> ciphers,
|
||||
SutProvider<ImportCiphersCommand> sutProvider)
|
||||
{
|
||||
var userId = Guid.NewGuid();
|
||||
folders.ForEach(f => f.UserId = userId);
|
||||
ciphers.ForEach(c => c.UserId = userId);
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<PersonalOwnershipPolicyRequirement>(userId)
|
||||
.Returns(new PersonalOwnershipPolicyRequirement { DisablePersonalOwnership = true });
|
||||
|
||||
var folderRelationships = new List<KeyValuePair<int, int>>();
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(() =>
|
||||
sutProvider.Sut.ImportIntoIndividualVaultAsync(folders, ciphers, folderRelationships, userId));
|
||||
|
||||
Assert.Equal("You cannot import items into your personal vault because you are a member of an organization which forbids it.", exception.Message);
|
||||
}
|
||||
|
||||
[Theory, BitAutoData]
|
||||
public async Task ImportIntoOrganizationalVaultAsync_Success(
|
||||
Organization organization,
|
||||
|
@ -1,5 +1,9 @@
|
||||
using System.Text.Json;
|
||||
using Bit.Core.AdminConsole.Entities;
|
||||
using Bit.Core.AdminConsole.Enums;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies;
|
||||
using Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
|
||||
using Bit.Core.AdminConsole.Services;
|
||||
using Bit.Core.Billing.Enums;
|
||||
using Bit.Core.Entities;
|
||||
using Bit.Core.Enums;
|
||||
@ -107,6 +111,98 @@ public class CipherServiceTests
|
||||
await sutProvider.GetDependency<ICipherRepository>().Received(1).ReplaceAsync(cipherDetails);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SaveDetailsAsync_PersonalVault_WithDisablePersonalOwnershipPolicyEnabled_Throws(
|
||||
SutProvider<CipherService> sutProvider,
|
||||
CipherDetails cipher,
|
||||
Guid savingUserId)
|
||||
{
|
||||
cipher.Id = default;
|
||||
cipher.UserId = savingUserId;
|
||||
cipher.OrganizationId = null;
|
||||
|
||||
sutProvider.GetDependency<IPolicyService>()
|
||||
.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.PersonalOwnership)
|
||||
.Returns(true);
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SaveDetailsAsync(cipher, savingUserId, null));
|
||||
Assert.Contains("restricted from saving items to your personal vault", exception.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SaveDetailsAsync_PersonalVault_WithDisablePersonalOwnershipPolicyDisabled_Succeeds(
|
||||
SutProvider<CipherService> sutProvider,
|
||||
CipherDetails cipher,
|
||||
Guid savingUserId)
|
||||
{
|
||||
cipher.Id = default;
|
||||
cipher.UserId = savingUserId;
|
||||
cipher.OrganizationId = null;
|
||||
|
||||
sutProvider.GetDependency<IPolicyService>()
|
||||
.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.PersonalOwnership)
|
||||
.Returns(false);
|
||||
|
||||
await sutProvider.Sut.SaveDetailsAsync(cipher, savingUserId, null);
|
||||
|
||||
await sutProvider.GetDependency<ICipherRepository>()
|
||||
.Received(1)
|
||||
.CreateAsync(cipher);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SaveDetailsAsync_PersonalVault_WithPolicyRequirementsEnabled_WithDisablePersonalOwnershipPolicyEnabled_Throws(
|
||||
SutProvider<CipherService> sutProvider,
|
||||
CipherDetails cipher,
|
||||
Guid savingUserId)
|
||||
{
|
||||
cipher.Id = default;
|
||||
cipher.UserId = savingUserId;
|
||||
cipher.OrganizationId = null;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<PersonalOwnershipPolicyRequirement>(savingUserId)
|
||||
.Returns(new PersonalOwnershipPolicyRequirement { DisablePersonalOwnership = true });
|
||||
|
||||
var exception = await Assert.ThrowsAsync<BadRequestException>(
|
||||
() => sutProvider.Sut.SaveDetailsAsync(cipher, savingUserId, null));
|
||||
Assert.Contains("restricted from saving items to your personal vault", exception.Message);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData]
|
||||
public async Task SaveDetailsAsync_PersonalVault_WithPolicyRequirementsEnabled_WithDisablePersonalOwnershipPolicyDisabled_Succeeds(
|
||||
SutProvider<CipherService> sutProvider,
|
||||
CipherDetails cipher,
|
||||
Guid savingUserId)
|
||||
{
|
||||
cipher.Id = default;
|
||||
cipher.UserId = savingUserId;
|
||||
cipher.OrganizationId = null;
|
||||
|
||||
sutProvider.GetDependency<IFeatureService>()
|
||||
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
|
||||
.Returns(true);
|
||||
|
||||
sutProvider.GetDependency<IPolicyRequirementQuery>()
|
||||
.GetAsync<PersonalOwnershipPolicyRequirement>(savingUserId)
|
||||
.Returns(new PersonalOwnershipPolicyRequirement { DisablePersonalOwnership = false });
|
||||
|
||||
await sutProvider.Sut.SaveDetailsAsync(cipher, savingUserId, null);
|
||||
|
||||
await sutProvider.GetDependency<ICipherRepository>()
|
||||
.Received(1)
|
||||
.CreateAsync(cipher);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[BitAutoData("")]
|
||||
[BitAutoData("Correct Time")]
|
||||
|
Reference in New Issue
Block a user