diff --git a/src/Api/Vault/Controllers/CiphersController.cs b/src/Api/Vault/Controllers/CiphersController.cs index d44d338215e1..8ba36d7c0cb0 100644 --- a/src/Api/Vault/Controllers/CiphersController.cs +++ b/src/Api/Vault/Controllers/CiphersController.cs @@ -1332,6 +1332,11 @@ await _cipherRepository.GetOrganizationDetailsByIdAsync(id) : throw new BadRequestException($"Max file size is {CipherService.MAX_FILE_SIZE_READABLE}."); } + if (cipher.GetAttachments().Values.Any(v => v.FileName == request.FileName)) + { + throw new BadRequestException("Items cannot have multiple attachments with the same file name"); + } + var (attachmentId, uploadUrl) = await _cipherService.CreateAttachmentForDelayedUploadAsync(cipher, request.Key, request.FileName, request.FileSize, request.AdminRequest, user.Id, request.LastKnownRevisionDate); diff --git a/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs b/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs index 7ddc31a7c3ee..9b80ffbceced 100644 --- a/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs +++ b/test/Api.Test/Vault/Controllers/CiphersControllerTests.cs @@ -2486,4 +2486,37 @@ public async Task DownloadAttachmentAsync_ValidToken_ReturnsFile( Assert.Equal(fileName, fileResult.FileDownloadName); Assert.Same(stream, fileResult.FileStream); } + + [Theory, BitAutoData] + public async Task PostAttachment_WithDuplicateFilename_ThrowsBadRequestError( + User user, Guid cipherId, string attachmentId, + SutProvider sutProvider) + { + var fileName = "shared-filename.txt"; + var metaData = new CipherAttachment.MetaData + { + AttachmentId = attachmentId, + FileName = fileName, + Size = 10, + }; + + sutProvider.GetDependency() + .GetUserByPrincipalAsync(Arg.Any()) + .Returns(user); + + var cipherDetails = new CipherDetails { Id = cipherId, UserId = user.Id, Type = CipherType.Login, Data = "{}", Attachments = JsonSerializer.Serialize( + new Dictionary { { attachmentId, metaData } })}; + sutProvider.GetDependency().GetByIdAsync(cipherId, user.Id) + .Returns(Task.FromResult(cipherDetails)); + + var exception = await Assert.ThrowsAsync( + () => sutProvider.Sut.PostAttachment(cipherId, new AttachmentRequestModel { + AdminRequest = false, + FileName = fileName, + FileSize = 10, + Key = "test-key" + }) + ); + Assert.Equal("Items cannot have multiple attachments with the same file name", exception.Message); + } }