mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 08:32:50 -05:00
post, upload, and save cipher attachment
This commit is contained in:
@ -9,6 +9,8 @@ using Bit.Core.Exceptions;
|
||||
using Bit.Core.Services;
|
||||
using Bit.Core;
|
||||
using Bit.Api.Utilities;
|
||||
using Bit.Core.Models.Data;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Bit.Api.Controllers
|
||||
{
|
||||
@ -219,13 +221,10 @@ namespace Bit.Api.Controllers
|
||||
string.IsNullOrWhiteSpace(model.FolderId) ? (Guid?)null : new Guid(model.FolderId), userId);
|
||||
}
|
||||
|
||||
[HttpPost("attachment")]
|
||||
[HttpPost("{id}/attachment")]
|
||||
[DisableFormValueModelBinding]
|
||||
public async Task Post(string id)
|
||||
public async Task PostAttachment(string id)
|
||||
{
|
||||
// throw for now
|
||||
throw new NotImplementedException();
|
||||
|
||||
if(!Request?.ContentType.Contains("multipart/") ?? true)
|
||||
{
|
||||
throw new BadRequestException("Invalid content.");
|
||||
@ -239,22 +238,16 @@ namespace Bit.Api.Controllers
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
await Request.GetFilesAsync(async (stream, fileName) =>
|
||||
await Request.GetFileAsync(async (stream, fileName) =>
|
||||
{
|
||||
var attachmentId = Guid.NewGuid();
|
||||
// TODO: store attachmentId + fileName reference in database
|
||||
var storedFilename = $"{idGuid}_{attachmentId}";
|
||||
await _attachmentStorageService.UploadAttachmentAsync(stream, storedFilename);
|
||||
await _cipherService.AttachAsync(cipher, stream, fileName, Request.ContentLength.GetValueOrDefault(0), userId);
|
||||
});
|
||||
}
|
||||
|
||||
[HttpDelete("{id}/attachment/{attachmentId}")]
|
||||
[HttpPost("{id}/attachment/{attachmentId}/delete")]
|
||||
public async Task Delete(string id, string attachmentId)
|
||||
public async Task DeleteAttachment(string id, string attachmentId)
|
||||
{
|
||||
// throw for now
|
||||
throw new NotImplementedException();
|
||||
|
||||
var idGuid = new Guid(id);
|
||||
var userId = _userService.GetProperUserId(User).Value;
|
||||
var cipher = await _cipherRepository.GetByIdAsync(idGuid, userId);
|
||||
@ -263,11 +256,9 @@ namespace Bit.Api.Controllers
|
||||
throw new NotFoundException();
|
||||
}
|
||||
|
||||
var attachmentIdGuid = new Guid(attachmentId);
|
||||
|
||||
// TODO: check and remove attachmentId from cipher in database
|
||||
|
||||
var storedFilename = $"{idGuid}_{attachmentId}";
|
||||
var storedFilename = $"{idGuid}/{attachmentId}";
|
||||
await _attachmentStorageService.DeleteAttachmentAsync(storedFilename);
|
||||
}
|
||||
}
|
||||
|
@ -12,23 +12,38 @@ namespace Bit.Api.Utilities
|
||||
{
|
||||
private static readonly FormOptions _defaultFormOptions = new FormOptions();
|
||||
|
||||
public static async Task GetFilesAsync(this HttpRequest request, Func<Stream, string, Task> callback)
|
||||
public static async Task GetFileAsync(this HttpRequest request, Func<Stream, string, Task> callback)
|
||||
{
|
||||
await request.GetFilesAsync(1, callback);
|
||||
}
|
||||
|
||||
private static async Task GetFilesAsync(this HttpRequest request, int? fileCount, Func<Stream, string, Task> callback)
|
||||
{
|
||||
var boundary = GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType),
|
||||
_defaultFormOptions.MultipartBoundaryLengthLimit);
|
||||
var reader = new MultipartReader(boundary, request.Body);
|
||||
|
||||
var section = await reader.ReadNextSectionAsync();
|
||||
while(section != null)
|
||||
var fileNumber = 1;
|
||||
while(section != null && fileNumber <= fileCount)
|
||||
{
|
||||
ContentDispositionHeaderValue content;
|
||||
if(ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out content) &&
|
||||
HasFileContentDisposition(content))
|
||||
{
|
||||
await callback(section.Body, HeaderUtilities.RemoveQuotes(content.FileName));
|
||||
var fileName = HeaderUtilities.RemoveQuotes(content.FileName) ?? string.Empty;
|
||||
await callback(section.Body, fileName);
|
||||
}
|
||||
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
if(fileNumber >= fileCount)
|
||||
{
|
||||
section = null;
|
||||
}
|
||||
else
|
||||
{
|
||||
section = await reader.ReadNextSectionAsync();
|
||||
fileNumber++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user