1
0
mirror of https://github.com/bitwarden/server.git synced 2025-07-03 00:52:49 -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:
Rui Tomé
2025-03-26 09:40:13 +00:00
committed by GitHub
parent d563f3f78a
commit f04a3d638b
7 changed files with 240 additions and 10 deletions

View File

@ -0,0 +1,26 @@
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
namespace Bit.Core.AdminConsole.OrganizationFeatures.Policies.PolicyRequirements;
/// <summary>
/// Policy requirements for the Disable Personal Ownership policy.
/// </summary>
public class PersonalOwnershipPolicyRequirement : IPolicyRequirement
{
/// <summary>
/// Indicates whether Personal Ownership is disabled for the user. If true, members are required to save items to an organization.
/// </summary>
public bool DisablePersonalOwnership { get; init; }
}
public class PersonalOwnershipPolicyRequirementFactory : BasePolicyRequirementFactory<PersonalOwnershipPolicyRequirement>
{
public override PolicyType PolicyType => PolicyType.PersonalOwnership;
public override PersonalOwnershipPolicyRequirement Create(IEnumerable<PolicyDetails> policyDetails)
{
var result = new PersonalOwnershipPolicyRequirement { DisablePersonalOwnership = policyDetails.Any() };
return result;
}
}

View File

@ -34,5 +34,6 @@ public static class PolicyServiceCollectionExtensions
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, DisableSendPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, SendOptionsPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, ResetPasswordPolicyRequirementFactory>();
services.AddScoped<IPolicyRequirementFactory<IPolicyRequirement>, PersonalOwnershipPolicyRequirementFactory>();
}
}

View File

@ -1,10 +1,13 @@
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.Context;
using Bit.Core.Entities;
using Bit.Core.Exceptions;
using Bit.Core.Platform.Push;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.ImportFeatures.Interfaces;
using Bit.Core.Tools.Models.Business;
@ -26,7 +29,8 @@ public class ImportCiphersCommand : IImportCiphersCommand
private readonly ICollectionRepository _collectionRepository;
private readonly IReferenceEventService _referenceEventService;
private readonly ICurrentContext _currentContext;
private readonly IPolicyRequirementQuery _policyRequirementQuery;
private readonly IFeatureService _featureService;
public ImportCiphersCommand(
ICipherRepository cipherRepository,
@ -37,7 +41,9 @@ public class ImportCiphersCommand : IImportCiphersCommand
IPushNotificationService pushService,
IPolicyService policyService,
IReferenceEventService referenceEventService,
ICurrentContext currentContext)
ICurrentContext currentContext,
IPolicyRequirementQuery policyRequirementQuery,
IFeatureService featureService)
{
_cipherRepository = cipherRepository;
_folderRepository = folderRepository;
@ -48,9 +54,10 @@ public class ImportCiphersCommand : IImportCiphersCommand
_policyService = policyService;
_referenceEventService = referenceEventService;
_currentContext = currentContext;
_policyRequirementQuery = policyRequirementQuery;
_featureService = featureService;
}
public async Task ImportIntoIndividualVaultAsync(
List<Folder> folders,
List<CipherDetails> ciphers,
@ -58,8 +65,11 @@ public class ImportCiphersCommand : IImportCiphersCommand
Guid importingUserId)
{
// Make sure the user can save new ciphers to their personal vault
var anyPersonalOwnershipPolicies = await _policyService.AnyPoliciesApplicableToUserAsync(importingUserId, PolicyType.PersonalOwnership);
if (anyPersonalOwnershipPolicies)
var isPersonalVaultRestricted = _featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements)
? (await _policyRequirementQuery.GetAsync<PersonalOwnershipPolicyRequirement>(importingUserId)).DisablePersonalOwnership
: await _policyService.AnyPoliciesApplicableToUserAsync(importingUserId, PolicyType.PersonalOwnership);
if (isPersonalVaultRestricted)
{
throw new BadRequestException("You cannot import items into your personal vault because you are " +
"a member of an organization which forbids it.");

View File

@ -1,5 +1,7 @@
using System.Text.Json;
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.Context;
using Bit.Core.Enums;
@ -41,6 +43,8 @@ public class CipherService : ICipherService
private readonly IReferenceEventService _referenceEventService;
private readonly ICurrentContext _currentContext;
private readonly IGetCipherPermissionsForUserQuery _getCipherPermissionsForUserQuery;
private readonly IPolicyRequirementQuery _policyRequirementQuery;
private readonly IFeatureService _featureService;
public CipherService(
ICipherRepository cipherRepository,
@ -58,7 +62,9 @@ public class CipherService : ICipherService
GlobalSettings globalSettings,
IReferenceEventService referenceEventService,
ICurrentContext currentContext,
IGetCipherPermissionsForUserQuery getCipherPermissionsForUserQuery)
IGetCipherPermissionsForUserQuery getCipherPermissionsForUserQuery,
IPolicyRequirementQuery policyRequirementQuery,
IFeatureService featureService)
{
_cipherRepository = cipherRepository;
_folderRepository = folderRepository;
@ -76,6 +82,8 @@ public class CipherService : ICipherService
_referenceEventService = referenceEventService;
_currentContext = currentContext;
_getCipherPermissionsForUserQuery = getCipherPermissionsForUserQuery;
_policyRequirementQuery = policyRequirementQuery;
_featureService = featureService;
}
public async Task SaveAsync(Cipher cipher, Guid savingUserId, DateTime? lastKnownRevisionDate,
@ -143,9 +151,11 @@ public class CipherService : ICipherService
}
else
{
// Make sure the user can save new ciphers to their personal vault
var anyPersonalOwnershipPolicies = await _policyService.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.PersonalOwnership);
if (anyPersonalOwnershipPolicies)
var isPersonalVaultRestricted = _featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements)
? (await _policyRequirementQuery.GetAsync<PersonalOwnershipPolicyRequirement>(savingUserId)).DisablePersonalOwnership
: await _policyService.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.PersonalOwnership);
if (isPersonalVaultRestricted)
{
throw new BadRequestException("Due to an Enterprise Policy, you are restricted from saving items to your personal vault.");
}