mirror of
https://github.com/bitwarden/server.git
synced 2025-05-23 04:21:05 -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:
parent
f8940e4be5
commit
e350daeeee
@ -11,6 +11,7 @@ using Bit.Api.Utilities;
|
|||||||
using Bit.Core.Models.Table;
|
using Bit.Core.Models.Table;
|
||||||
using Bit.Core.Utilities;
|
using Bit.Core.Utilities;
|
||||||
using Bit.Core.Settings;
|
using Bit.Core.Settings;
|
||||||
|
using Bit.Core.Models.Api.Response;
|
||||||
|
|
||||||
namespace Bit.Api.Controllers
|
namespace Bit.Api.Controllers
|
||||||
{
|
{
|
||||||
@ -21,17 +22,20 @@ namespace Bit.Api.Controllers
|
|||||||
private readonly ISendRepository _sendRepository;
|
private readonly ISendRepository _sendRepository;
|
||||||
private readonly IUserService _userService;
|
private readonly IUserService _userService;
|
||||||
private readonly ISendService _sendService;
|
private readonly ISendService _sendService;
|
||||||
|
private readonly ISendFileStorageService _sendFileStorageService;
|
||||||
private readonly GlobalSettings _globalSettings;
|
private readonly GlobalSettings _globalSettings;
|
||||||
|
|
||||||
public SendsController(
|
public SendsController(
|
||||||
ISendRepository sendRepository,
|
ISendRepository sendRepository,
|
||||||
IUserService userService,
|
IUserService userService,
|
||||||
ISendService sendService,
|
ISendService sendService,
|
||||||
|
ISendFileStorageService sendFileStorageService,
|
||||||
GlobalSettings globalSettings)
|
GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
_sendRepository = sendRepository;
|
_sendRepository = sendRepository;
|
||||||
_userService = userService;
|
_userService = userService;
|
||||||
_sendService = sendService;
|
_sendService = sendService;
|
||||||
|
_sendFileStorageService = sendFileStorageService;
|
||||||
_globalSettings = globalSettings;
|
_globalSettings = globalSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,6 +63,17 @@ namespace Bit.Api.Controllers
|
|||||||
return new ObjectResult(new SendAccessResponseModel(send, _globalSettings));
|
return new ObjectResult(new SendAccessResponseModel(send, _globalSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[AllowAnonymous]
|
||||||
|
[HttpGet("access/file/{id}")]
|
||||||
|
public async Task<SendFileDownloadDataResponseModel> GetSendFileDownloadData(string id)
|
||||||
|
{
|
||||||
|
return new SendFileDownloadDataResponseModel()
|
||||||
|
{
|
||||||
|
Id = id,
|
||||||
|
Url = await _sendFileStorageService.GetSendFileDownloadUrlAsync(id),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[HttpGet("{id}")]
|
[HttpGet("{id}")]
|
||||||
public async Task<SendResponseModel> Get(string id)
|
public async Task<SendResponseModel> Get(string id)
|
||||||
{
|
{
|
||||||
|
@ -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)
|
public SendFileModel(SendFileData data, GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
Id = data.Id;
|
Id = data.Id;
|
||||||
Url = $"{globalSettings.Send.BaseUrl}/{data.Id}";
|
|
||||||
FileName = data.FileName;
|
FileName = data.FileName;
|
||||||
Size = data.SizeString;
|
Size = data.SizeString;
|
||||||
SizeName = CoreHelpers.ReadableBytesSize(data.Size);
|
SizeName = CoreHelpers.ReadableBytesSize(data.Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string Id { get; set; }
|
public string Id { get; set; }
|
||||||
public string Url { get; set; }
|
|
||||||
[EncryptedString]
|
[EncryptedString]
|
||||||
[EncryptedStringLength(1000)]
|
[EncryptedStringLength(1000)]
|
||||||
public string FileName { get; set; }
|
public string FileName { get; set; }
|
||||||
|
@ -11,5 +11,6 @@ namespace Bit.Core.Services
|
|||||||
Task DeleteFileAsync(string fileId);
|
Task DeleteFileAsync(string fileId);
|
||||||
Task DeleteFilesForOrganizationAsync(Guid organizationId);
|
Task DeleteFilesForOrganizationAsync(Guid organizationId);
|
||||||
Task DeleteFilesForUserAsync(Guid userId);
|
Task DeleteFilesForUserAsync(Guid userId);
|
||||||
|
Task<string> GetSendFileDownloadUrlAsync(string fileId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ namespace Bit.Core.Services
|
|||||||
{
|
{
|
||||||
private const string FilesContainerName = "sendfiles";
|
private const string FilesContainerName = "sendfiles";
|
||||||
|
|
||||||
|
private static readonly TimeSpan _downloadLinkLiveTime = TimeSpan.FromMinutes(1);
|
||||||
private readonly CloudBlobClient _blobClient;
|
private readonly CloudBlobClient _blobClient;
|
||||||
private CloudBlobContainer _sendFilesContainer;
|
private CloudBlobContainer _sendFilesContainer;
|
||||||
|
|
||||||
@ -55,12 +56,25 @@ namespace Bit.Core.Services
|
|||||||
await InitAsync();
|
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()
|
private async Task InitAsync()
|
||||||
{
|
{
|
||||||
if (_sendFilesContainer == null)
|
if (_sendFilesContainer == null)
|
||||||
{
|
{
|
||||||
_sendFilesContainer = _blobClient.GetContainerReference(FilesContainerName);
|
_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
|
public class LocalSendStorageService : ISendFileStorageService
|
||||||
{
|
{
|
||||||
private readonly string _baseDirPath;
|
private readonly string _baseDirPath;
|
||||||
|
private readonly string _baseSendUrl;
|
||||||
|
|
||||||
public LocalSendStorageService(
|
public LocalSendStorageService(
|
||||||
GlobalSettings globalSettings)
|
GlobalSettings globalSettings)
|
||||||
{
|
{
|
||||||
_baseDirPath = globalSettings.Send.BaseDirectory;
|
_baseDirPath = globalSettings.Send.BaseDirectory;
|
||||||
|
_baseSendUrl = globalSettings.Send.BaseUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UploadNewFileAsync(Stream stream, Send send, string fileId)
|
public async Task UploadNewFileAsync(Stream stream, Send send, string fileId)
|
||||||
@ -42,6 +44,12 @@ namespace Bit.Core.Services
|
|||||||
await InitAsync();
|
await InitAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<string> GetSendFileDownloadUrlAsync(string fileId)
|
||||||
|
{
|
||||||
|
await InitAsync();
|
||||||
|
return $"{_baseSendUrl}/{fileId}";
|
||||||
|
}
|
||||||
|
|
||||||
private void DeleteFileIfExists(string path)
|
private void DeleteFileIfExists(string path)
|
||||||
{
|
{
|
||||||
if (File.Exists(path))
|
if (File.Exists(path))
|
||||||
|
@ -26,5 +26,10 @@ namespace Bit.Core.Services
|
|||||||
{
|
{
|
||||||
return Task.FromResult(0);
|
return Task.FromResult(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Task<string> GetSendFileDownloadUrlAsync(string fileId)
|
||||||
|
{
|
||||||
|
return Task.FromResult((string)null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user