1
0
mirror of https://github.com/bitwarden/server.git synced 2025-05-22 20:11:04 -05:00
bitwarden/src/Api/Tools/Models/Request/SendRequestModel.cs
Graham Walker 818934487f
PM-18939 refactoring send service to 'cqrs' (#5652)
* PM-18939 refactoring send service to 'cqrs'

* PM-18939 fixing import issue with sendValidationService

* PM-18939 fixing code based on PR comments

* PM-18339 reverting to previous code in test

* PM-18939 adding XMLdocs to services

* PM-18939 reverting send validation methods

* PM-18939 updating code to match main

* PM-18939 reverting validateUserCanSaveAsync to match main

* PM-18939 fill our param and return sections of XMLdocs

* PM-18939 updating XMLdocs based on PR comments

* Update src/Core/Tools/SendFeatures/Commands/Interfaces/IAnonymousSendCommand.cs

Co-authored-by:  Audrey  <ajensen@bitwarden.com>

* Update src/Core/Tools/SendFeatures/Commands/Interfaces/INonAnonymousSendCommand.cs

Co-authored-by:  Audrey  <ajensen@bitwarden.com>

* Update src/Core/Tools/SendFeatures/Commands/Interfaces/INonAnonymousSendCommand.cs

Co-authored-by:  Audrey  <ajensen@bitwarden.com>

* Update src/Core/Tools/SendFeatures/Services/Interfaces/ISendStorageService.cs

Co-authored-by:  Audrey  <ajensen@bitwarden.com>

* PM-18939 adding commits to change tuple to enum type

* PM-18939 resetting stream position to 0 when uploading file

* PM-18939 updating XMLdocs based on PR comments

* PM-18939 updating XMLdocs

* PM-18939 removing circular dependency

* PM-18939 fixing based on comments

* PM-18939 updating method name and documentation

---------

Co-authored-by:  Audrey  <ajensen@bitwarden.com>
2025-05-19 22:59:30 -05:00

154 lines
5.3 KiB
C#

using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Bit.Core.Exceptions;
using Bit.Core.Tools.Entities;
using Bit.Core.Tools.Enums;
using Bit.Core.Tools.Models.Data;
using Bit.Core.Tools.Services;
using Bit.Core.Utilities;
namespace Bit.Api.Tools.Models.Request;
public class SendRequestModel
{
public SendType Type { get; set; }
public long? FileLength { get; set; } = null;
[EncryptedString]
[EncryptedStringLength(1000)]
public string Name { get; set; }
[EncryptedString]
[EncryptedStringLength(1000)]
public string Notes { get; set; }
[Required]
[EncryptedString]
[EncryptedStringLength(1000)]
public string Key { get; set; }
[Range(1, int.MaxValue)]
public int? MaxAccessCount { get; set; }
public DateTime? ExpirationDate { get; set; }
[Required]
public DateTime? DeletionDate { get; set; }
public SendFileModel File { get; set; }
public SendTextModel Text { get; set; }
[StringLength(1000)]
public string Password { get; set; }
[Required]
public bool? Disabled { get; set; }
public bool? HideEmail { get; set; }
public Send ToSend(Guid userId, ISendAuthorizationService sendAuthorizationService)
{
var send = new Send
{
Type = Type,
UserId = (Guid?)userId
};
ToSend(send, sendAuthorizationService);
return send;
}
public (Send, SendFileData) ToSend(Guid userId, string fileName, ISendAuthorizationService sendAuthorizationService)
{
var send = ToSendBase(new Send
{
Type = Type,
UserId = (Guid?)userId
}, sendAuthorizationService);
var data = new SendFileData(Name, Notes, fileName);
return (send, data);
}
public Send ToSend(Send existingSend, ISendAuthorizationService sendAuthorizationService)
{
existingSend = ToSendBase(existingSend, sendAuthorizationService);
switch (existingSend.Type)
{
case SendType.File:
var fileData = JsonSerializer.Deserialize<SendFileData>(existingSend.Data);
fileData.Name = Name;
fileData.Notes = Notes;
existingSend.Data = JsonSerializer.Serialize(fileData, JsonHelpers.IgnoreWritingNull);
break;
case SendType.Text:
existingSend.Data = JsonSerializer.Serialize(ToSendTextData(), JsonHelpers.IgnoreWritingNull);
break;
default:
throw new ArgumentException("Unsupported type: " + nameof(Type) + ".");
}
return existingSend;
}
public void ValidateCreation()
{
var now = DateTime.UtcNow;
// Add 1 minute for a sane buffer and client clock float
var nowPlus1Minute = now.AddMinutes(1);
if (ExpirationDate.HasValue && ExpirationDate.Value <= nowPlus1Minute)
{
throw new BadRequestException("You cannot create a Send that is already expired. " +
"Adjust the expiration date and try again.");
}
ValidateEdit();
}
public void ValidateEdit()
{
var now = DateTime.UtcNow;
// Add 1 minute for a sane buffer and client clock float
var nowPlus1Minute = now.AddMinutes(1);
if (DeletionDate.HasValue)
{
if (DeletionDate.Value <= nowPlus1Minute)
{
throw new BadRequestException("You cannot have a Send with a deletion date in the past. " +
"Adjust the deletion date and try again.");
}
if (DeletionDate.Value > now.AddDays(31))
{
throw new BadRequestException("You cannot have a Send with a deletion date that far " +
"into the future. Adjust the Deletion Date to a value less than 31 days from now " +
"and try again.");
}
}
if (ExpirationDate.HasValue)
{
if (ExpirationDate.Value <= nowPlus1Minute)
{
throw new BadRequestException("You cannot have a Send with an expiration date in the past. " +
"Adjust the expiration date and try again.");
}
if (ExpirationDate.Value > DeletionDate.Value)
{
throw new BadRequestException("You cannot have a Send with an expiration date greater than the deletion date. " +
"Adjust the expiration date and try again.");
}
}
}
private Send ToSendBase(Send existingSend, ISendAuthorizationService authorizationService)
{
existingSend.Key = Key;
existingSend.ExpirationDate = ExpirationDate;
existingSend.DeletionDate = DeletionDate.Value;
existingSend.MaxAccessCount = MaxAccessCount;
if (!string.IsNullOrWhiteSpace(Password))
{
existingSend.Password = authorizationService.HashPassword(Password);
}
existingSend.Disabled = Disabled.GetValueOrDefault();
existingSend.HideEmail = HideEmail.GetValueOrDefault();
return existingSend;
}
private SendTextData ToSendTextData()
{
return new SendTextData(Name, Notes, Text.Text, Text.Hidden);
}
}
public class SendWithIdRequestModel : SendRequestModel
{
[Required]
public Guid? Id { get; set; }
}