Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 4 additions & 14 deletions src/Core/Tools/ImportFeatures/ImportCiphersCommand.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
ο»Ώ// FIXME: Update this file to be null safe and then delete the line below
#nullable disable

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.Tools.ImportFeatures.Interfaces;
using Bit.Core.Vault.Entities;
using Bit.Core.Vault.Models.Data;
Expand All @@ -22,12 +19,10 @@ public class ImportCiphersCommand : IImportCiphersCommand
private readonly ICipherRepository _cipherRepository;
private readonly IFolderRepository _folderRepository;
private readonly IPushNotificationService _pushService;
private readonly IPolicyService _policyService;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ICollectionRepository _collectionRepository;
private readonly IPolicyRequirementQuery _policyRequirementQuery;
private readonly IFeatureService _featureService;

public ImportCiphersCommand(
ICipherRepository cipherRepository,
Expand All @@ -36,19 +31,15 @@ public ImportCiphersCommand(
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
IPushNotificationService pushService,
IPolicyService policyService,
IPolicyRequirementQuery policyRequirementQuery,
IFeatureService featureService)
IPolicyRequirementQuery policyRequirementQuery)
{
_cipherRepository = cipherRepository;
_folderRepository = folderRepository;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_collectionRepository = collectionRepository;
_pushService = pushService;
_policyService = policyService;
_policyRequirementQuery = policyRequirementQuery;
_featureService = featureService;
}

public async Task ImportIntoIndividualVaultAsync(
Expand All @@ -58,11 +49,10 @@ public async Task ImportIntoIndividualVaultAsync(
Guid importingUserId)
{
// Make sure the user can save new ciphers to their personal vault
var organizationDataOwnershipEnabled = _featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements)
? (await _policyRequirementQuery.GetAsync<OrganizationDataOwnershipPolicyRequirement>(importingUserId)).State == OrganizationDataOwnershipState.Enabled
: await _policyService.AnyPoliciesApplicableToUserAsync(importingUserId, PolicyType.OrganizationDataOwnership);
var organizationDataOwnershipPolicyRequirement =
await _policyRequirementQuery.GetAsync<OrganizationDataOwnershipPolicyRequirement>(importingUserId);

if (organizationDataOwnershipEnabled)
if (organizationDataOwnershipPolicyRequirement.State == OrganizationDataOwnershipState.Enabled)
{
throw new BadRequestException("You cannot import items into your personal vault because you are " +
"a member of an organization which forbids it.");
Expand Down
15 changes: 3 additions & 12 deletions src/Core/Vault/Services/Implementations/CipherService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@

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.Pricing;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
Expand All @@ -32,14 +30,12 @@ public class CipherService : ICipherService
private readonly ICollectionRepository _collectionRepository;
private readonly IUserRepository _userRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly IOrganizationUserRepository _organizationUserRepository;
private readonly ICollectionCipherRepository _collectionCipherRepository;
private readonly ISecurityTaskRepository _securityTaskRepository;
private readonly IPushNotificationService _pushService;
private readonly IAttachmentStorageService _attachmentStorageService;
private readonly IEventService _eventService;
private readonly IUserService _userService;
private readonly IPolicyService _policyService;
private readonly GlobalSettings _globalSettings;
private const long _fileSizeLeeway = 1024L * 1024L; // 1MB
private readonly IGetCipherPermissionsForUserQuery _getCipherPermissionsForUserQuery;
Expand All @@ -54,14 +50,12 @@ public CipherService(
ICollectionRepository collectionRepository,
IUserRepository userRepository,
IOrganizationRepository organizationRepository,
IOrganizationUserRepository organizationUserRepository,
ICollectionCipherRepository collectionCipherRepository,
ISecurityTaskRepository securityTaskRepository,
IPushNotificationService pushService,
IAttachmentStorageService attachmentStorageService,
IEventService eventService,
IUserService userService,
IPolicyService policyService,
GlobalSettings globalSettings,
IGetCipherPermissionsForUserQuery getCipherPermissionsForUserQuery,
IPolicyRequirementQuery policyRequirementQuery,
Expand All @@ -74,14 +68,12 @@ public CipherService(
_collectionRepository = collectionRepository;
_userRepository = userRepository;
_organizationRepository = organizationRepository;
_organizationUserRepository = organizationUserRepository;
_collectionCipherRepository = collectionCipherRepository;
_securityTaskRepository = securityTaskRepository;
_pushService = pushService;
_attachmentStorageService = attachmentStorageService;
_eventService = eventService;
_userService = userService;
_policyService = policyService;
_globalSettings = globalSettings;
_getCipherPermissionsForUserQuery = getCipherPermissionsForUserQuery;
_policyRequirementQuery = policyRequirementQuery;
Expand Down Expand Up @@ -152,11 +144,10 @@ public async Task SaveDetailsAsync(CipherDetails cipher, Guid savingUserId, Date
}
else
{
var organizationDataOwnershipEnabled = _featureService.IsEnabled(FeatureFlagKeys.PolicyRequirements)
? (await _policyRequirementQuery.GetAsync<OrganizationDataOwnershipPolicyRequirement>(savingUserId)).State == OrganizationDataOwnershipState.Enabled
: await _policyService.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.OrganizationDataOwnership);
var organizationDataOwnershipPolicyRequirement =
await _policyRequirementQuery.GetAsync<OrganizationDataOwnershipPolicyRequirement>(savingUserId);

if (organizationDataOwnershipEnabled)
if (organizationDataOwnershipPolicyRequirement.State == OrganizationDataOwnershipState.Enabled)
{
throw new BadRequestException("Due to an Enterprise Policy, you are restricted from saving items to your personal vault.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
ο»Ώusing Bit.Core.AdminConsole.Entities;
using Bit.Core.AdminConsole.Enums;
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
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.ImportFeatures;
using Bit.Core.Vault.Entities;
Expand All @@ -26,43 +23,11 @@ namespace Bit.Core.Test.Tools.ImportFeatures;
public class ImportCiphersAsyncCommandTests
{
[Theory, BitAutoData]
public async Task ImportIntoIndividualVaultAsync_Success(
public async Task ImportIntoIndividualVaultAsync_WithOrganizationDataOwnershipPolicyDisabled_Success(
Guid importingUserId,
List<CipherDetails> ciphers,
SutProvider<ImportCiphersCommand> sutProvider)
{
sutProvider.GetDependency<IPolicyService>()
.AnyPoliciesApplicableToUserAsync(importingUserId, PolicyType.OrganizationDataOwnership)
.Returns(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>>();

// Act
await sutProvider.Sut.ImportIntoIndividualVaultAsync(folders, ciphers, folderRelationships, importingUserId);

// Assert
await sutProvider.GetDependency<ICipherRepository>()
.Received(1)
.CreateAsync(importingUserId, ciphers, Arg.Any<List<Folder>>());
await sutProvider.GetDependency<IPushNotificationService>().Received(1).PushSyncVaultAsync(importingUserId);
}

[Theory, BitAutoData]
public async Task ImportIntoIndividualVaultAsync_WithPolicyRequirementsEnabled_WithOrganizationDataOwnershipPolicyDisabled_Success(
Guid importingUserId,
List<CipherDetails> ciphers,
SutProvider<ImportCiphersCommand> sutProvider)
{
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
.Returns(true);

sutProvider.GetDependency<IPolicyRequirementQuery>()
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(importingUserId)
.Returns(new OrganizationDataOwnershipPolicyRequirement(
Expand All @@ -86,29 +51,7 @@ await sutProvider.GetDependency<ICipherRepository>()
}

[Theory, BitAutoData]
public async Task ImportIntoIndividualVaultAsync_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<IPolicyService>()
.AnyPoliciesApplicableToUserAsync(userId, PolicyType.OrganizationDataOwnership)
.Returns(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 ImportIntoIndividualVaultAsync_WithPolicyRequirementsEnabled_WithOrganizationDataOwnershipPolicyEnabled_ThrowsBadRequestException(
public async Task ImportIntoIndividualVaultAsync_WithOrganizationDataOwnershipPolicyEnabled_ThrowsBadRequestException(
List<Folder> folders,
List<CipherDetails> ciphers,
SutProvider<ImportCiphersCommand> sutProvider)
Expand All @@ -117,10 +60,6 @@ public async Task ImportIntoIndividualVaultAsync_WithPolicyRequirementsEnabled_W
folders.ForEach(f => f.UserId = userId);
ciphers.ForEach(c => c.UserId = userId);

sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
.Returns(true);

sutProvider.GetDependency<IPolicyRequirementQuery>()
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(userId)
.Returns(new OrganizationDataOwnershipPolicyRequirement(
Expand All @@ -142,10 +81,6 @@ public async Task ImportIntoIndividualVaultAsync_FavoriteCiphers_PersistsFavorit
SutProvider<ImportCiphersCommand> sutProvider
)
{
sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
.Returns(true);

sutProvider.GetDependency<IPolicyRequirementQuery>()
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(importingUserId)
.Returns(new OrganizationDataOwnershipPolicyRequirement(
Expand Down Expand Up @@ -337,9 +272,11 @@ public async Task ImportIntoIndividualVaultAsync_WithArchivedCiphers_PreservesAr
ciphers[0].UserId = importingUserId;
ciphers[0].ArchivedDate = archivedDate;

sutProvider.GetDependency<IPolicyService>()
.AnyPoliciesApplicableToUserAsync(importingUserId, PolicyType.OrganizationDataOwnership)
.Returns(false);
sutProvider.GetDependency<IPolicyRequirementQuery>()
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(importingUserId)
.Returns(new OrganizationDataOwnershipPolicyRequirement(
OrganizationDataOwnershipState.Disabled,
[]));

sutProvider.GetDependency<IFolderRepository>()
.GetManyByUserIdAsync(importingUserId)
Expand Down
53 changes: 1 addition & 52 deletions test/Core.Test/Vault/Services/CipherServiceTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
using Bit.Core.AdminConsole.Models.Data.Organizations.Policies;
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.Billing.Pricing;
using Bit.Core.Billing.Pricing.Premium;
Expand Down Expand Up @@ -238,52 +237,6 @@ public async Task SaveDetailsAsync_PersonalVault_WithOrganizationDataOwnershipPo
cipher.UserId = savingUserId;
cipher.OrganizationId = null;

sutProvider.GetDependency<IPolicyService>()
.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.OrganizationDataOwnership)
.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_WithOrganizationDataOwnershipPolicyDisabled_Succeeds(
SutProvider<CipherService> sutProvider,
CipherDetails cipher,
Guid savingUserId)
{
cipher.Id = default;
cipher.UserId = savingUserId;
cipher.OrganizationId = null;

sutProvider.GetDependency<IPolicyService>()
.AnyPoliciesApplicableToUserAsync(savingUserId, PolicyType.OrganizationDataOwnership)
.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_WithOrganizationDataOwnershipPolicyEnabled_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<OrganizationDataOwnershipPolicyRequirement>(savingUserId)
.Returns(new OrganizationDataOwnershipPolicyRequirement(
Expand All @@ -297,7 +250,7 @@ public async Task SaveDetailsAsync_PersonalVault_WithPolicyRequirementsEnabled_W

[Theory]
[BitAutoData]
public async Task SaveDetailsAsync_PersonalVault_WithPolicyRequirementsEnabled_WithOrganizationDataOwnershipPolicyDisabled_Succeeds(
public async Task SaveDetailsAsync_PersonalVault_WithOrganizationDataOwnershipPolicyDisabled_Succeeds(
SutProvider<CipherService> sutProvider,
CipherDetails cipher,
Guid savingUserId)
Expand All @@ -306,10 +259,6 @@ public async Task SaveDetailsAsync_PersonalVault_WithPolicyRequirementsEnabled_W
cipher.UserId = savingUserId;
cipher.OrganizationId = null;

sutProvider.GetDependency<IFeatureService>()
.IsEnabled(FeatureFlagKeys.PolicyRequirements)
.Returns(true);

sutProvider.GetDependency<IPolicyRequirementQuery>()
.GetAsync<OrganizationDataOwnershipPolicyRequirement>(savingUserId)
.Returns(new OrganizationDataOwnershipPolicyRequirement(
Expand Down
Loading