1
0
mirror of https://github.com/bitwarden/server synced 2025-12-22 11:13:27 +00:00
Files
server/src/Core/Services/Implementations/LocalSendStorageService.cs
Matt Gibson 8d5fc21b51 Prepare for send direct upload (#1174)
* Add sendId to path

Event Grid returns the blob path, which will be used to grab a Send and verify file size

* Re-validate access upon file download

Increment access count only when file is downloaded. File
name and size are leaked, but this is a good first step toward
solving the access-download race
2021-03-01 15:01:04 -06:00

88 lines
2.5 KiB
C#

using System.Threading.Tasks;
using System.IO;
using System;
using Bit.Core.Models.Table;
using Bit.Core.Settings;
using System.Linq;
namespace Bit.Core.Services
{
public class LocalSendStorageService : ISendFileStorageService
{
private readonly string _baseDirPath;
private readonly string _baseSendUrl;
private string RelativeFilePath(Send send, string fileID) => $"{send.Id}/{fileID}";
private string FilePath(Send send, string fileID) => $"{_baseDirPath}/{RelativeFilePath(send, fileID)}";
public LocalSendStorageService(
GlobalSettings globalSettings)
{
_baseDirPath = globalSettings.Send.BaseDirectory;
_baseSendUrl = globalSettings.Send.BaseUrl;
}
public async Task UploadNewFileAsync(Stream stream, Send send, string fileId)
{
await InitAsync();
var path = FilePath(send, fileId);
Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var fs = File.Create(path))
{
stream.Seek(0, SeekOrigin.Begin);
await stream.CopyToAsync(fs);
}
}
public async Task DeleteFileAsync(Send send, string fileId)
{
await InitAsync();
var path = FilePath(send, fileId);
DeleteFileIfExists(path);
DeleteDirectoryIfExistsAndEmpty(Path.GetDirectoryName(path));
}
public async Task DeleteFilesForOrganizationAsync(Guid organizationId)
{
await InitAsync();
}
public async Task DeleteFilesForUserAsync(Guid userId)
{
await InitAsync();
}
public async Task<string> GetSendFileDownloadUrlAsync(Send send, string fileId)
{
await InitAsync();
return $"{_baseSendUrl}/{RelativeFilePath(send, fileId)}";
}
private void DeleteFileIfExists(string path)
{
if (File.Exists(path))
{
File.Delete(path);
}
}
private void DeleteDirectoryIfExistsAndEmpty(string path)
{
if (Directory.Exists(path) && !Directory.EnumerateFiles(path).Any())
{
Directory.Delete(path);
}
}
private Task InitAsync()
{
if (!Directory.Exists(_baseDirPath))
{
Directory.CreateDirectory(_baseDirPath);
}
return Task.FromResult(0);
}
}
}