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, byte[] data, AttachmentUploadDataResponse uploadDataResponse, CipherString encKey) { sutProvider.GetDependency().EncryptAsync(fileName, Arg.Any()) .Returns(new CipherString(fileName)); sutProvider.GetDependency().EncryptToBytesAsync(data, Arg.Any()) .Returns(data); sutProvider.GetDependency().MakeEncKeyAsync(Arg.Any()).Returns(new Tuple(null, encKey)); sutProvider.GetDependency().PostCipherAttachmentAsync(cipher.Id, Arg.Any()) .Returns(uploadDataResponse); await sutProvider.Sut.SaveAttachmentRawWithServerAsync(cipher, fileName, data); await sutProvider.GetDependency().Received(1) .UploadCipherAttachmentFileAsync(uploadDataResponse, fileName, data); } [Theory] [InlineUserCipherAutoData(HttpStatusCode.NotFound)] [InlineUserCipherAutoData(HttpStatusCode.MethodNotAllowed)] public async Task SaveWithServerAsync_FallsBackToLegacyFormData(HttpStatusCode statusCode, SutProvider sutProvider, Cipher cipher, string fileName, byte[] data, CipherResponse response, CipherString encKey) { sutProvider.GetDependency().EncryptAsync(fileName, Arg.Any()) .Returns(new CipherString(fileName)); sutProvider.GetDependency().EncryptToBytesAsync(data, Arg.Any()) .Returns(data); sutProvider.GetDependency().MakeEncKeyAsync(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); await sutProvider.GetDependency().Received(1) .PostCipherAttachmentLegacyAsync(cipher.Id, Arg.Any()); } [Theory, UserCipherAutoData] public async Task SaveWithServerAsync_ThrowsOnBadRequestApiException(SutProvider sutProvider, Cipher cipher, string fileName, byte[] data, CipherString encKey) { sutProvider.GetDependency().EncryptAsync(fileName, Arg.Any()) .Returns(new CipherString(fileName)); sutProvider.GetDependency().EncryptToBytesAsync(data, Arg.Any()) .Returns(data); sutProvider.GetDependency().MakeEncKeyAsync(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)); 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); sutProvider.GetDependency().Received(1).GetAttachmentData(cipherId, attachment.Id); } } }