Files
server/src/Core/Tools/Services/Implementations/SendService.cs

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

344 lines
12 KiB
C#
Raw Normal View History

using System.Text.Json;
using Bit.Core.Context;
using Bit.Core.Entities;
using Bit.Core.Enums;
using Bit.Core.Exceptions;
using Bit.Core.Models.Data.Organizations.Policies;
using Bit.Core.Repositories;
using Bit.Core.Services;
using Bit.Core.Settings;
using Bit.Core.Tools.Entities;
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.Models.Business;
using Bit.Core.Tools.Models.Data;
using Bit.Core.Tools.Repositories;
using Bit.Core.Utilities;
using Microsoft.AspNetCore.Identity;
namespace Bit.Core.Tools.Services;
2022-08-29 16:06:55 -04:00
public class SendService : ISendService
{
public const long MAX_FILE_SIZE = Constants.FileSize501mb;
public const string MAX_FILE_SIZE_READABLE = "500 MB";
private readonly ISendRepository _sendRepository;
private readonly IUserRepository _userRepository;
private readonly IPolicyRepository _policyRepository;
private readonly IUserService _userService;
private readonly IOrganizationRepository _organizationRepository;
private readonly ISendFileStorageService _sendFileStorageService;
private readonly IPasswordHasher<User> _passwordHasher;
private readonly IPushNotificationService _pushService;
2021-02-25 13:40:26 -05:00
private readonly IReferenceEventService _referenceEventService;
private readonly GlobalSettings _globalSettings;
private readonly ICurrentContext _currentContext;
2021-02-25 13:40:26 -05:00
private const long _fileSizeLeeway = 1024L * 1024L; // 1MB
2022-08-29 16:06:55 -04:00
public SendService(
2021-02-25 13:40:26 -05:00
ISendRepository sendRepository,
IUserRepository userRepository,
IUserService userService,
IOrganizationRepository organizationRepository,
2021-02-25 13:40:26 -05:00
ISendFileStorageService sendFileStorageService,
IPasswordHasher<User> passwordHasher,
IPushNotificationService pushService,
2021-02-25 13:40:26 -05:00
IReferenceEventService referenceEventService,
GlobalSettings globalSettings,
IPolicyRepository policyRepository,
ICurrentContext currentContext)
2022-08-29 16:06:55 -04:00
{
_sendRepository = sendRepository;
_userRepository = userRepository;
_userService = userService;
_policyRepository = policyRepository;
_organizationRepository = organizationRepository;
_sendFileStorageService = sendFileStorageService;
_passwordHasher = passwordHasher;
_pushService = pushService;
_referenceEventService = referenceEventService;
_globalSettings = globalSettings;
_currentContext = currentContext;
2022-08-29 16:06:55 -04:00
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
public async Task SaveSendAsync(Send send)
{
// Make sure user can save Sends
await ValidateUserCanSaveAsync(send.UserId, send);
2022-08-29 16:06:55 -04:00
2021-02-25 13:40:26 -05:00
if (send.Id == default(Guid))
{
await _sendRepository.CreateAsync(send);
await _pushService.PushSyncSendCreateAsync(send);
await RaiseReferenceEventAsync(send, ReferenceEventType.SendCreated);
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
else
{
send.RevisionDate = DateTime.UtcNow;
await _sendRepository.UpsertAsync(send);
await _pushService.PushSyncSendUpdateAsync(send);
}
2022-08-29 16:06:55 -04:00
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
public async Task<string> SaveFileSendAsync(Send send, SendFileData data, long fileLength)
2022-08-29 16:06:55 -04:00
{
if (send.Type != SendType.File)
{
throw new BadRequestException("Send is not of type \"file\".");
}
if (fileLength < 1)
{
throw new BadRequestException("No file data.");
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
var storageBytesRemaining = await StorageRemainingForSendAsync(send);
if (storageBytesRemaining < fileLength)
2022-08-29 14:53:16 -04:00
{
throw new BadRequestException("Not enough storage available.");
2022-08-29 14:53:16 -04:00
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
var fileId = Utilities.CoreHelpers.SecureRandomString(32, upper: false, special: false);
try
{
data.Id = fileId;
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
data.Size = fileLength;
data.Validated = false;
send.Data = JsonSerializer.Serialize(data,
JsonHelpers.IgnoreWritingNull);
await SaveSendAsync(send);
return await _sendFileStorageService.GetSendFileUploadUrlAsync(send, fileId);
}
2022-08-29 16:06:55 -04:00
catch
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
{
// Clean up since this is not transactional
await _sendFileStorageService.DeleteFileAsync(send, fileId);
throw;
2022-08-29 16:06:55 -04:00
}
}
2022-08-29 14:53:16 -04:00
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
public async Task UploadFileToExistingSendAsync(Stream stream, Send send)
2022-08-29 16:06:55 -04:00
{
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
if (send?.Data == null)
2022-08-29 16:06:55 -04:00
{
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
throw new BadRequestException("Send does not have file data");
2022-08-29 16:06:55 -04:00
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
if (send.Type != SendType.File)
2022-08-29 14:53:16 -04:00
{
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
throw new BadRequestException("Not a File Type Send.");
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
var data = JsonSerializer.Deserialize<SendFileData>(send.Data);
if (data.Validated)
{
throw new BadRequestException("File has already been uploaded.");
2022-08-29 14:53:16 -04:00
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
await _sendFileStorageService.UploadNewFileAsync(stream, send, data.Id);
2022-08-29 16:06:55 -04:00
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
if (!await ValidateSendFile(send))
2022-08-29 14:53:16 -04:00
{
throw new BadRequestException("File received does not match expected file length.");
2022-08-29 16:06:55 -04:00
}
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
public async Task<bool> ValidateSendFile(Send send)
2022-08-29 16:06:55 -04:00
{
var fileData = JsonSerializer.Deserialize<SendFileData>(send.Data);
2022-08-29 14:53:16 -04:00
var (valid, realSize) = await _sendFileStorageService.ValidateFileAsync(send, fileData.Id, fileData.Size, _fileSizeLeeway);
if (!valid || realSize > MAX_FILE_SIZE)
{
// File reported differs in size from that promised. Must be a rogue client. Delete Send
await DeleteSendAsync(send);
return false;
2022-08-29 16:06:55 -04:00
}
// Update Send data if necessary
if (realSize != fileData.Size)
2022-08-29 16:06:55 -04:00
{
fileData.Size = realSize.Value;
2022-08-29 14:53:16 -04:00
}
fileData.Validated = true;
send.Data = JsonSerializer.Serialize(fileData,
JsonHelpers.IgnoreWritingNull);
await SaveSendAsync(send);
return valid;
2022-08-29 16:06:55 -04:00
}
public async Task DeleteSendAsync(Send send)
2022-08-29 16:06:55 -04:00
{
await _sendRepository.DeleteAsync(send);
if (send.Type == Enums.SendType.File)
2022-08-29 14:53:16 -04:00
{
var data = JsonSerializer.Deserialize<SendFileData>(send.Data);
await _sendFileStorageService.DeleteFileAsync(send, data.Id);
}
await _pushService.PushSyncSendDeleteAsync(send);
2022-08-29 16:06:55 -04:00
}
public (bool grant, bool passwordRequiredError, bool passwordInvalidError) SendCanBeAccessed(Send send,
string password)
2022-08-29 16:06:55 -04:00
{
var now = DateTime.UtcNow;
if (send == null || send.MaxAccessCount.GetValueOrDefault(int.MaxValue) <= send.AccessCount ||
send.ExpirationDate.GetValueOrDefault(DateTime.MaxValue) < now || send.Disabled ||
send.DeletionDate < now)
{
return (false, false, false);
2022-08-29 16:06:55 -04:00
}
if (!string.IsNullOrWhiteSpace(send.Password))
2022-08-29 16:06:55 -04:00
{
if (string.IsNullOrWhiteSpace(password))
2022-08-29 16:06:55 -04:00
{
return (false, true, false);
2022-08-29 16:06:55 -04:00
}
var passwordResult = _passwordHasher.VerifyHashedPassword(new User(), send.Password, password);
if (passwordResult == PasswordVerificationResult.SuccessRehashNeeded)
{
send.Password = HashPassword(password);
}
if (passwordResult == PasswordVerificationResult.Failed)
{
return (false, false, true);
}
2022-08-29 16:06:55 -04:00
}
return (true, false, false);
2022-08-29 16:06:55 -04:00
}
// Response: Send, password required, password invalid
public async Task<(string, bool, bool)> GetSendFileDownloadUrlAsync(Send send, string fileId, string password)
2022-08-29 16:06:55 -04:00
{
if (send.Type != SendType.File)
2022-08-29 16:06:55 -04:00
{
throw new BadRequestException("Can only get a download URL for a file type of Send");
}
var (grantAccess, passwordRequired, passwordInvalid) = SendCanBeAccessed(send, password);
2022-08-29 16:06:55 -04:00
if (!grantAccess)
{
return (null, passwordRequired, passwordInvalid);
2022-08-29 14:53:16 -04:00
}
send.AccessCount++;
await _sendRepository.ReplaceAsync(send);
await _pushService.PushSyncSendUpdateAsync(send);
return (await _sendFileStorageService.GetSendFileDownloadUrlAsync(send, fileId), false, false);
2022-08-29 16:06:55 -04:00
}
// Response: Send, password required, password invalid
public async Task<(Send, bool, bool)> AccessAsync(Guid sendId, string password)
2022-08-29 16:06:55 -04:00
{
var send = await _sendRepository.GetByIdAsync(sendId);
var (grantAccess, passwordRequired, passwordInvalid) = SendCanBeAccessed(send, password);
if (!grantAccess)
2022-08-29 16:06:55 -04:00
{
return (null, passwordRequired, passwordInvalid);
2022-08-29 14:53:16 -04:00
}
// TODO: maybe move this to a simple ++ sproc?
if (send.Type != SendType.File)
2022-08-29 14:53:16 -04:00
{
// File sends are incremented during file download
2021-02-25 13:40:26 -05:00
send.AccessCount++;
2022-08-29 16:06:55 -04:00
}
await _sendRepository.ReplaceAsync(send);
2021-02-25 13:40:26 -05:00
await _pushService.PushSyncSendUpdateAsync(send);
await RaiseReferenceEventAsync(send, ReferenceEventType.SendAccessed);
return (send, false, false);
}
2021-02-25 13:40:26 -05:00
private async Task RaiseReferenceEventAsync(Send send, ReferenceEventType eventType)
2022-08-29 16:06:55 -04:00
{
await _referenceEventService.RaiseEventAsync(new ReferenceEvent
2022-08-29 16:06:55 -04:00
{
2021-02-25 13:40:26 -05:00
Id = send.UserId ?? default,
Type = eventType,
Source = ReferenceEventSource.User,
SendType = send.Type,
MaxAccessCount = send.MaxAccessCount,
HasPassword = !string.IsNullOrWhiteSpace(send.Password),
});
}
2021-02-25 13:40:26 -05:00
public string HashPassword(string password)
2022-08-29 16:06:55 -04:00
{
2021-02-25 13:40:26 -05:00
return _passwordHasher.HashPassword(new User(), password);
}
private async Task ValidateUserCanSaveAsync(Guid? userId, Send send)
2022-08-29 16:06:55 -04:00
{
if (!userId.HasValue || (!_currentContext.Organizations?.Any() ?? true))
{
return;
}
var disableSendPolicyCount = await _policyRepository.GetCountByTypeApplicableToUserIdAsync(userId.Value,
PolicyType.DisableSend);
if (disableSendPolicyCount > 0)
{
throw new BadRequestException("Due to an Enterprise Policy, you are only able to delete an existing Send.");
2022-08-29 14:53:16 -04:00
}
if (send.HideEmail.GetValueOrDefault())
2022-08-29 14:53:16 -04:00
{
var sendOptionsPolicies = await _policyRepository.GetManyByTypeApplicableToUserIdAsync(userId.Value, PolicyType.SendOptions);
if (sendOptionsPolicies.Any(p => p.GetDataModel<SendOptionsPolicyData>()?.DisableHideEmail ?? false))
{
throw new BadRequestException("Due to an Enterprise Policy, you are not allowed to hide your email address from recipients when creating or editing a Send.");
}
2022-08-29 16:06:55 -04:00
}
}
private async Task<long> StorageRemainingForSendAsync(Send send)
2022-08-29 16:06:55 -04:00
{
var storageBytesRemaining = 0L;
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
if (send.UserId.HasValue)
2022-08-29 16:06:55 -04:00
{
var user = await _userRepository.GetByIdAsync(send.UserId.Value);
if (!await _userService.CanAccessPremium(user))
{
throw new BadRequestException("You must have premium status to use file Sends.");
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
if (!user.EmailVerified)
{
throw new BadRequestException("You must confirm your email to use file Sends.");
2022-08-29 14:53:16 -04:00
}
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
if (user.Premium)
{
storageBytesRemaining = user.StorageBytesRemaining();
}
2021-02-25 13:40:26 -05:00
else
{
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
// Users that get access to file storage/premium from their organization get the default
// 1 GB max storage.
storageBytesRemaining = user.StorageBytesRemaining(
_globalSettings.SelfHosted ? (short)10240 : (short)1);
2022-08-29 16:06:55 -04:00
}
}
2021-02-25 13:40:26 -05:00
else if (send.OrganizationId.HasValue)
2022-08-29 16:06:55 -04:00
{
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
var org = await _organizationRepository.GetByIdAsync(send.OrganizationId.Value);
if (!org.MaxStorageGb.HasValue)
{
throw new BadRequestException("This organization cannot use file sends.");
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
}
2022-08-29 14:53:16 -04:00
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
storageBytesRemaining = org.StorageBytesRemaining();
}
2022-08-29 16:06:55 -04:00
Direct upload to Azure/Local (#1188) * Direct upload to azure To validate file sizes in the event of a rogue client, Azure event webhooks will be hooked up to AzureValidateFile. Sends outside of a grace size will be deleted as non-compliant. TODO: LocalSendFileStorageService direct upload method/endpoint. * Quick respond to no-body event calls These shouldn't happen, but might if some errant get requests occur * Event Grid only POSTS to webhook * Enable local storage direct file upload * Increase file size difference leeway * Upload through service * Fix LocalFileSendStorage It turns out that multipartHttpStreams do not have a length until read. this causes all long files to be "invalid". We need to write the entire stream, then validate length, just like Azure. the difference is, We can return an exception to local storage admonishing the client for lying * Update src/Api/Utilities/ApiHelpers.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Do not delete directory if it has files * Allow large uploads for self hosted instances * Fix formatting * Re-verfiy access and increment access count on download of Send File * Update src/Core/Services/Implementations/SendService.cs Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com> * Add back in original Send upload * Update size and mark as validated upon Send file validation * Log azure file validation errors * Lint fix Co-authored-by: Chad Scharf <3904944+cscharf@users.noreply.github.com>
2021-03-21 23:01:19 -05:00
return storageBytesRemaining;
}
}