mirror of
https://github.com/bitwarden/server.git
synced 2025-07-02 00:22:50 -05:00
Use sas token for send downloads (#1157)
* Remove Url from SendFileModel Url is now generated on the fly with limited lifetime. New model houses the download url generated * Create API endpoint for getting Send file download url * Generate limited-life Azure download urls * Lint fix
This commit is contained in:
@ -0,0 +1,10 @@
|
||||
namespace Bit.Core.Models.Api.Response
|
||||
{
|
||||
public class SendFileDownloadDataResponseModel : ResponseModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public SendFileDownloadDataResponseModel() : base("send-fileDownload") { }
|
||||
}
|
||||
}
|
@ -11,14 +11,12 @@ namespace Bit.Core.Models.Api
|
||||
public SendFileModel(SendFileData data, GlobalSettings globalSettings)
|
||||
{
|
||||
Id = data.Id;
|
||||
Url = $"{globalSettings.Send.BaseUrl}/{data.Id}";
|
||||
FileName = data.FileName;
|
||||
Size = data.SizeString;
|
||||
SizeName = CoreHelpers.ReadableBytesSize(data.Size);
|
||||
}
|
||||
|
||||
public string Id { get; set; }
|
||||
public string Url { get; set; }
|
||||
[EncryptedString]
|
||||
[EncryptedStringLength(1000)]
|
||||
public string FileName { get; set; }
|
||||
|
@ -11,5 +11,6 @@ namespace Bit.Core.Services
|
||||
Task DeleteFileAsync(string fileId);
|
||||
Task DeleteFilesForOrganizationAsync(Guid organizationId);
|
||||
Task DeleteFilesForUserAsync(Guid userId);
|
||||
Task<string> GetSendFileDownloadUrlAsync(string fileId);
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ namespace Bit.Core.Services
|
||||
{
|
||||
private const string FilesContainerName = "sendfiles";
|
||||
|
||||
private static readonly TimeSpan _downloadLinkLiveTime = TimeSpan.FromMinutes(1);
|
||||
private readonly CloudBlobClient _blobClient;
|
||||
private CloudBlobContainer _sendFilesContainer;
|
||||
|
||||
@ -55,12 +56,25 @@ namespace Bit.Core.Services
|
||||
await InitAsync();
|
||||
}
|
||||
|
||||
public async Task<string> GetSendFileDownloadUrlAsync(string fileId)
|
||||
{
|
||||
await InitAsync();
|
||||
var blob = _sendFilesContainer.GetBlockBlobReference(fileId);
|
||||
var accessPolicy = new SharedAccessBlobPolicy()
|
||||
{
|
||||
SharedAccessExpiryTime = DateTime.UtcNow.Add(_downloadLinkLiveTime),
|
||||
Permissions = SharedAccessBlobPermissions.Read
|
||||
};
|
||||
|
||||
return blob.Uri + blob.GetSharedAccessSignature(accessPolicy);
|
||||
}
|
||||
|
||||
private async Task InitAsync()
|
||||
{
|
||||
if (_sendFilesContainer == null)
|
||||
{
|
||||
_sendFilesContainer = _blobClient.GetContainerReference(FilesContainerName);
|
||||
await _sendFilesContainer.CreateIfNotExistsAsync(BlobContainerPublicAccessType.Blob, null, null);
|
||||
await _sendFilesContainer.CreateIfNotExistsAsync(BlobContainerPublicAccessType.Off, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,13 @@ namespace Bit.Core.Services
|
||||
public class LocalSendStorageService : ISendFileStorageService
|
||||
{
|
||||
private readonly string _baseDirPath;
|
||||
private readonly string _baseSendUrl;
|
||||
|
||||
public LocalSendStorageService(
|
||||
GlobalSettings globalSettings)
|
||||
{
|
||||
_baseDirPath = globalSettings.Send.BaseDirectory;
|
||||
_baseSendUrl = globalSettings.Send.BaseUrl;
|
||||
}
|
||||
|
||||
public async Task UploadNewFileAsync(Stream stream, Send send, string fileId)
|
||||
@ -42,6 +44,12 @@ namespace Bit.Core.Services
|
||||
await InitAsync();
|
||||
}
|
||||
|
||||
public async Task<string> GetSendFileDownloadUrlAsync(string fileId)
|
||||
{
|
||||
await InitAsync();
|
||||
return $"{_baseSendUrl}/{fileId}";
|
||||
}
|
||||
|
||||
private void DeleteFileIfExists(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
|
@ -26,5 +26,10 @@ namespace Bit.Core.Services
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task<string> GetSendFileDownloadUrlAsync(string fileId)
|
||||
{
|
||||
return Task.FromResult((string)null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user