You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
217 lines
11 KiB
217 lines
11 KiB
using Bit.Core.Entities; |
|
using Bit.Core.Exceptions; |
|
using Bit.Core.Repositories; |
|
using Bit.Core.Services; |
|
using Bit.Core.Test.AutoFixture.CipherFixtures; |
|
using Bit.Test.Common.AutoFixture; |
|
using Castle.Core.Internal; |
|
using Core.Models.Data; |
|
using NSubstitute; |
|
using Xunit; |
|
|
|
namespace Bit.Core.Test.Services |
|
{ |
|
public class CipherServiceTests |
|
{ |
|
[Theory, UserCipherAutoData] |
|
public async Task SaveAsync_WrongRevisionDate_Throws(SutProvider<CipherService> sutProvider, Cipher cipher) |
|
{ |
|
var lastKnownRevisionDate = cipher.RevisionDate.AddDays(-1); |
|
|
|
var exception = await Assert.ThrowsAsync<BadRequestException>( |
|
() => sutProvider.Sut.SaveAsync(cipher, cipher.UserId.Value, lastKnownRevisionDate)); |
|
Assert.Contains("out of date", exception.Message); |
|
} |
|
|
|
[Theory, UserCipherAutoData] |
|
public async Task SaveDetailsAsync_WrongRevisionDate_Throws(SutProvider<CipherService> sutProvider, |
|
CipherDetails cipherDetails) |
|
{ |
|
var lastKnownRevisionDate = cipherDetails.RevisionDate.AddDays(-1); |
|
|
|
var exception = await Assert.ThrowsAsync<BadRequestException>( |
|
() => sutProvider.Sut.SaveDetailsAsync(cipherDetails, cipherDetails.UserId.Value, lastKnownRevisionDate)); |
|
Assert.Contains("out of date", exception.Message); |
|
} |
|
|
|
[Theory, UserCipherAutoData] |
|
public async Task ShareAsync_WrongRevisionDate_Throws(SutProvider<CipherService> sutProvider, Cipher cipher, |
|
Organization organization, List<Guid> collectionIds) |
|
{ |
|
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization); |
|
var lastKnownRevisionDate = cipher.RevisionDate.AddDays(-1); |
|
|
|
var exception = await Assert.ThrowsAsync<BadRequestException>( |
|
() => sutProvider.Sut.ShareAsync(cipher, cipher, organization.Id, collectionIds, cipher.UserId.Value, |
|
lastKnownRevisionDate)); |
|
Assert.Contains("out of date", exception.Message); |
|
} |
|
|
|
[Theory, UserCipherAutoData("99ab4f6c-44f8-4ff5-be7a-75c37c33c69e")] |
|
public async Task ShareManyAsync_WrongRevisionDate_Throws(SutProvider<CipherService> sutProvider, |
|
IEnumerable<Cipher> ciphers, Guid organizationId, List<Guid> collectionIds) |
|
{ |
|
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId) |
|
.Returns(new Organization |
|
{ |
|
PlanType = Enums.PlanType.EnterpriseAnnually, |
|
MaxStorageGb = 100 |
|
}); |
|
|
|
var cipherInfos = ciphers.Select(c => (c, (DateTime?)c.RevisionDate.AddDays(-1))); |
|
|
|
var exception = await Assert.ThrowsAsync<BadRequestException>( |
|
() => sutProvider.Sut.ShareManyAsync(cipherInfos, organizationId, collectionIds, ciphers.First().UserId.Value)); |
|
Assert.Contains("out of date", exception.Message); |
|
} |
|
|
|
[Theory] |
|
[InlineUserCipherAutoData("")] |
|
[InlineUserCipherAutoData("Correct Time")] |
|
public async Task SaveAsync_CorrectRevisionDate_Passes(string revisionDateString, |
|
SutProvider<CipherService> sutProvider, Cipher cipher) |
|
{ |
|
var lastKnownRevisionDate = string.IsNullOrEmpty(revisionDateString) ? (DateTime?)null : cipher.RevisionDate; |
|
|
|
await sutProvider.Sut.SaveAsync(cipher, cipher.UserId.Value, lastKnownRevisionDate); |
|
await sutProvider.GetDependency<ICipherRepository>().Received(1).ReplaceAsync(cipher); |
|
} |
|
|
|
[Theory] |
|
[InlineUserCipherAutoData("")] |
|
[InlineUserCipherAutoData("Correct Time")] |
|
public async Task SaveDetailsAsync_CorrectRevisionDate_Passes(string revisionDateString, |
|
SutProvider<CipherService> sutProvider, CipherDetails cipherDetails) |
|
{ |
|
var lastKnownRevisionDate = string.IsNullOrEmpty(revisionDateString) ? (DateTime?)null : cipherDetails.RevisionDate; |
|
|
|
await sutProvider.Sut.SaveDetailsAsync(cipherDetails, cipherDetails.UserId.Value, lastKnownRevisionDate); |
|
await sutProvider.GetDependency<ICipherRepository>().Received(1).ReplaceAsync(cipherDetails); |
|
} |
|
|
|
[Theory] |
|
[InlineUserCipherAutoData("")] |
|
[InlineUserCipherAutoData("Correct Time")] |
|
public async Task ShareAsync_CorrectRevisionDate_Passes(string revisionDateString, |
|
SutProvider<CipherService> sutProvider, Cipher cipher, Organization organization, List<Guid> collectionIds) |
|
{ |
|
var lastKnownRevisionDate = string.IsNullOrEmpty(revisionDateString) ? (DateTime?)null : cipher.RevisionDate; |
|
var cipherRepository = sutProvider.GetDependency<ICipherRepository>(); |
|
cipherRepository.ReplaceAsync(cipher, collectionIds).Returns(true); |
|
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id).Returns(organization); |
|
|
|
await sutProvider.Sut.ShareAsync(cipher, cipher, organization.Id, collectionIds, cipher.UserId.Value, |
|
lastKnownRevisionDate); |
|
await cipherRepository.Received(1).ReplaceAsync(cipher, collectionIds); |
|
} |
|
|
|
[Theory] |
|
[InlineKnownUserCipherAutoData(userId: "99ab4f6c-44f8-4ff5-be7a-75c37c33c69e", "")] |
|
[InlineKnownUserCipherAutoData(userId: "99ab4f6c-44f8-4ff5-be7a-75c37c33c69e", "CorrectTime")] |
|
public async Task ShareManyAsync_CorrectRevisionDate_Passes(string revisionDateString, |
|
SutProvider<CipherService> sutProvider, IEnumerable<Cipher> ciphers, Organization organization, List<Guid> collectionIds) |
|
{ |
|
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organization.Id) |
|
.Returns(new Organization |
|
{ |
|
PlanType = Enums.PlanType.EnterpriseAnnually, |
|
MaxStorageGb = 100 |
|
}); |
|
|
|
var cipherInfos = ciphers.Select(c => (c, |
|
string.IsNullOrEmpty(revisionDateString) ? null : (DateTime?)c.RevisionDate)); |
|
var sharingUserId = ciphers.First().UserId.Value; |
|
|
|
await sutProvider.Sut.ShareManyAsync(cipherInfos, organization.Id, collectionIds, sharingUserId); |
|
await sutProvider.GetDependency<ICipherRepository>().Received(1).UpdateCiphersAsync(sharingUserId, |
|
Arg.Is<IEnumerable<Cipher>>(arg => arg.Except(ciphers).IsNullOrEmpty())); |
|
} |
|
|
|
[Theory] |
|
[InlineKnownUserCipherAutoData("c64d8a15-606e-41d6-9c7e-174d4d8f3b2e", "c64d8a15-606e-41d6-9c7e-174d4d8f3b2e")] |
|
[InlineOrganizationCipherAutoData("c64d8a15-606e-41d6-9c7e-174d4d8f3b2e")] |
|
public async Task RestoreAsync_UpdatesCipher(Guid restoringUserId, Cipher cipher, SutProvider<CipherService> sutProvider) |
|
{ |
|
sutProvider.GetDependency<ICipherRepository>().GetCanEditByIdAsync(restoringUserId, cipher.Id).Returns(true); |
|
|
|
var initialRevisionDate = new DateTime(1970, 1, 1, 0, 0, 0); |
|
cipher.DeletedDate = initialRevisionDate; |
|
cipher.RevisionDate = initialRevisionDate; |
|
|
|
await sutProvider.Sut.RestoreAsync(cipher, restoringUserId, cipher.OrganizationId.HasValue); |
|
|
|
Assert.Null(cipher.DeletedDate); |
|
Assert.NotEqual(initialRevisionDate, cipher.RevisionDate); |
|
} |
|
|
|
[Theory] |
|
[InlineKnownUserCipherAutoData("c64d8a15-606e-41d6-9c7e-174d4d8f3b2e", "c64d8a15-606e-41d6-9c7e-174d4d8f3b2e")] |
|
public async Task RestoreManyAsync_UpdatesCiphers(Guid restoringUserId, IEnumerable<CipherDetails> ciphers, |
|
SutProvider<CipherService> sutProvider) |
|
{ |
|
var previousRevisionDate = DateTime.UtcNow; |
|
foreach (var cipher in ciphers) |
|
{ |
|
cipher.RevisionDate = previousRevisionDate; |
|
} |
|
|
|
var revisionDate = previousRevisionDate + TimeSpan.FromMinutes(1); |
|
sutProvider.GetDependency<ICipherRepository>().RestoreAsync(Arg.Any<IEnumerable<Guid>>(), restoringUserId) |
|
.Returns(revisionDate); |
|
|
|
await sutProvider.Sut.RestoreManyAsync(ciphers, restoringUserId); |
|
|
|
foreach (var cipher in ciphers) |
|
{ |
|
Assert.Null(cipher.DeletedDate); |
|
Assert.Equal(revisionDate, cipher.RevisionDate); |
|
} |
|
} |
|
|
|
[Theory] |
|
[InlineUserCipherAutoData] |
|
public async Task ShareManyAsync_FreeOrgWithAttachment_Throws(SutProvider<CipherService> sutProvider, |
|
IEnumerable<Cipher> ciphers, Guid organizationId, List<Guid> collectionIds) |
|
{ |
|
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId).Returns(new Organization |
|
{ |
|
PlanType = Enums.PlanType.Free |
|
}); |
|
ciphers.FirstOrDefault().Attachments = |
|
"{\"attachment1\":{\"Size\":\"250\",\"FileName\":\"superCoolFile\"," |
|
+ "\"Key\":\"superCoolFile\",\"ContainerName\":\"testContainer\",\"Validated\":false}}"; |
|
|
|
var cipherInfos = ciphers.Select(c => (c, |
|
(DateTime?)c.RevisionDate)); |
|
var sharingUserId = ciphers.First().UserId.Value; |
|
|
|
var exception = await Assert.ThrowsAsync<BadRequestException>( |
|
() => sutProvider.Sut.ShareManyAsync(cipherInfos, organizationId, collectionIds, sharingUserId)); |
|
Assert.Contains("This organization cannot use attachments", exception.Message); |
|
} |
|
|
|
[Theory] |
|
[InlineUserCipherAutoData] |
|
public async Task ShareManyAsync_PaidOrgWithAttachment_Passes(SutProvider<CipherService> sutProvider, |
|
IEnumerable<Cipher> ciphers, Guid organizationId, List<Guid> collectionIds) |
|
{ |
|
sutProvider.GetDependency<IOrganizationRepository>().GetByIdAsync(organizationId) |
|
.Returns(new Organization |
|
{ |
|
PlanType = Enums.PlanType.EnterpriseAnnually, |
|
MaxStorageGb = 100 |
|
}); |
|
ciphers.FirstOrDefault().Attachments = |
|
"{\"attachment1\":{\"Size\":\"250\",\"FileName\":\"superCoolFile\"," |
|
+ "\"Key\":\"superCoolFile\",\"ContainerName\":\"testContainer\",\"Validated\":false}}"; |
|
|
|
var cipherInfos = ciphers.Select(c => (c, |
|
(DateTime?)c.RevisionDate)); |
|
var sharingUserId = ciphers.First().UserId.Value; |
|
|
|
await sutProvider.Sut.ShareManyAsync(cipherInfos, organizationId, collectionIds, sharingUserId); |
|
await sutProvider.GetDependency<ICipherRepository>().Received(1).UpdateCiphersAsync(sharingUserId, |
|
Arg.Is<IEnumerable<Cipher>>(arg => arg.Except(ciphers).IsNullOrEmpty())); |
|
} |
|
} |
|
}
|
|
|