using System; using System.Net; using System.Net.Http; using System.Threading.Tasks; using Bit.Core.Abstractions; using Bit.Core.Exceptions; using Bit.Core.Models.Domain; using Bit.Core.Models.Request; using Bit.Core.Models.Response; using Bit.Core.Models.View; using Bit.Core.Services; using Bit.Core.Test.AutoFixture; using Bit.Test.Common.AutoFixture; using Bit.Test.Common.AutoFixture.Attributes; using NSubstitute; using NSubstitute.ExceptionExtensions; using Xunit; namespace Bit.Core.Test.Services { public class CipherServiceTests { [Theory, UserCipherAutoData] public async Task SaveWithServerAsync_PrefersFileUploadService(SutProvider sutProvider, Cipher cipher, string fileName, EncByteArray data, AttachmentUploadDataResponse uploadDataResponse, EncString encKey) { var encFileName = new EncString(fileName); sutProvider.GetDependency().EncryptAsync(fileName, Arg.Any()) .Returns(encFileName); sutProvider.GetDependency().EncryptToBytesAsync(data.Buffer, Arg.Any()) .Returns(data); sutProvider.GetDependency().MakeDataEncKeyAsync(Arg.Any()).Returns(new Tuple(null, encKey)); sutProvider.GetDependency().PostCipherAttachmentAsync(cipher.Id, Arg.Any()) .Returns(uploadDataResponse); await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer); await sutProvider.GetDependency().Received(1) .UploadCipherAttachmentFileAsync(uploadDataResponse, encFileName, data); } [Theory] [InlineUserCipherAutoData(HttpStatusCode.NotFound)] [InlineUserCipherAutoData(HttpStatusCode.MethodNotAllowed)] public async Task SaveWithServerAsync_FallsBackToLegacyFormData(HttpStatusCode statusCode, SutProvider sutProvider, Cipher cipher, string fileName, EncByteArray data, CipherResponse response, EncString encKey) { sutProvider.GetDependency().EncryptAsync(fileName, Arg.Any()) .Returns(new EncString(fileName)); sutProvider.GetDependency().EncryptToBytesAsync(data.Buffer, Arg.Any()) .Returns(data); sutProvider.GetDependency().MakeDataEncKeyAsync(Arg.Any()).Returns(new Tuple(null, encKey)); sutProvider.GetDependency().PostCipherAttachmentAsync(cipher.Id, Arg.Any()) .Throws(new ApiException(new ErrorResponse { StatusCode = statusCode })); sutProvider.GetDependency().PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any()) .Returns(response); await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer); await sutProvider.GetDependency().Received(1) .PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any()); } [Theory, UserCipherAutoData] public async Task SaveWithServerAsync_ThrowsOnBadRequestApiException(SutProvider sutProvider, Cipher cipher, string fileName, EncByteArray data, EncString encKey) { sutProvider.GetDependency().EncryptAsync(fileName, Arg.Any()) .Returns(new EncString(fileName)); sutProvider.GetDependency().EncryptToBytesAsync(data.Buffer, Arg.Any()) .Returns(data); sutProvider.GetDependency().MakeDataEncKeyAsync(Arg.Any()) .Returns(new Tuple(null, encKey)); var expectedException = new ApiException(new ErrorResponse { StatusCode = HttpStatusCode.BadRequest }); sutProvider.GetDependency().PostCipherAttachmentAsync(cipher.Id, Arg.Any()) .Throws(expectedException); var actualException = await Assert.ThrowsAsync(async () => await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data.Buffer)); Assert.Equal(expectedException.Error.StatusCode, actualException.Error.StatusCode); } [Theory, CustomAutoData(typeof(SutProviderCustomization), typeof(SymmetricCryptoKeyCustomization))] public async Task DownloadAndDecryptAttachmentAsync_RequestsTimeLimitedUrl(SutProvider sutProvider, string cipherId, AttachmentView attachment, AttachmentResponse response) { sutProvider.GetDependency().GetAttachmentData(cipherId, attachment.Id) .Returns(response); await sutProvider.Sut.DownloadAndDecryptAttachmentAsync(cipherId, attachment, null); await sutProvider.GetDependency().Received(1).GetAttachmentData(cipherId, attachment.Id); } } }